programing

JPA - EclipseLink - 기본 스키마를 변경하는 방법

magicmemo 2023. 8. 19. 10:07
반응형

JPA - EclipseLink - 기본 스키마를 변경하는 방법

저는 웹 로직과 오라클을 사용하여 웹 애플리케이션을 프로그래밍하고 있습니다.데이터 소스는 JNDI를 통해 구성되며 테이블에 DML을 넣을 수 있지만 DDL을 할 수 없는 제한된 데이터베이스 사용자를 사용합니다.짐작하시겠지만, 해당 사용자는 해당 테이블의 소유자가 아니지만 액세스 권한이 부여되어 있습니다.

그가 GUSTER_USER라고 가정해 보겠습니다.

응용 프로그램이 JPA + EclipseLink를 사용하고 있으며 이미 많은 엔티티가 정의되어 있습니다.스키마를 변경할 속성을 각 엔티티 클래스에 기록하지 않습니다.이 코드로 세션 커스터마이저를 사용해 보았습니다.

public class MyCustomizer implements SessionCustomizer{

    @Override
    public void customize(Session session) throws Exception {

    session.executeNonSelectingSQL("ALTER SESSION SET CURRENT_SCHEMA = OWNERS_SCHEMA");
    }
}

초기화되지 않은 것이 있는 것 같습니다. Null 포인터 예외가 발생합니다. 연결을 사용하기 전에 이 방법으로 연결 스키마를 변경할 수 있는지조차 모르겠습니다.샘플이나 아이디어는?

도움을 주셔서 미리 감사드립니다!

모든 엔티티가 동일한 스키마를 사용하는 경우 xml 매핑 파일을 사용하여 기본 스키마를 정의할 수 있습니다.

이와 같은 것이 작동해야 합니다(예: JPA 2.0의 경우, 1.0의 경우 schemaLocation 변경).

orm.xml:

<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
    version="2.0">
    <persistence-unit-metadata>
        <persistence-unit-defaults>
            <schema>OWNERS_SCHEMA</schema>
        </persistence-unit-defaults>
    </persistence-unit-metadata>   
    . . .
</entity-mappings>

persistence.xml:

<persistence
    xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0" >
    <persistence-unit name="foo">
        . . .
        <mapping-file>orm.xml</mapping-file>
        . . .
    </persistence-unit>
</persistence>

프로그램적으로 할 수 있습니다.각 세션의 기본 스키마 값을 구성할 수 있습니다.

public class MySessionCustomizer implements SessionCustomizer {

  private static String schemaName;

  public static void setSchemaName(String schemaName) {
      MySessionCustomizer.schemaName = schemaName;
  }

  @Override
  public void customize(Session session) throws Exception {
      if (StringUtils.hasText(this.schemaName)) {
          session.getLogin().setTableQualifier(this.schemaName);
      }
  }
}

그런 다음 세션 사용자 지정기를 엔티티 관리자 공장 속성으로 설정합니다.

PersistenceUnitProperties.SESSION_CUSTOMIZER 

예.

propertiesMap.put(PersistenceUnitProperties.SESSION_CUSTOMIZER, MySessionCustomizer.class.getName());

데이터베이스를 쿼리하기 직전에 EJB를 사용하므로 Interceptors를 사용하면 현재 인증된 사용자를 확인하여 EJB 컨텍스트에서 스키마를 설정할 수 있습니다.

그러면 엔티티 관리자를 빌드할 때 올바른 스키마를 설정할 수 있습니다.이런 식으로 테이블 이름 앞에 스키마를 지정하지 않음으로써 PostgreSQL은 다음을 살펴볼 것입니다.search_path쿼리할 스키마를 결정합니다.

<!-- language: lang-java -->

public class Interceptor {

    Logger logger = Logger.getLogger(Interceptor.class);

    /**
     * 
     * @param ctx is always null before being passed to EJB implementation. We always query database
     * for populating context data, making user's session accessible to all EJB implementations
     * @return
     * @throws Exception
     */
    @SuppressWarnings({ "unchecked", "unused" })
    @AroundInvoke
    public Object intercept(InvocationContext ctx) throws Exception {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        String ejbName = ctx.getMethod().getDeclaringClass().getSimpleName();
        String methodName = ctx.getMethod().getName();
        Boolean override_schema = false;
        String overridden_schema = "";

        logger.info("Intercepting " + ejbName + "." + methodName);

        if(auth != null) {

            UserDetails userDetails = (UserDetails)auth.getPrincipal();
            String username = userDetails.getUsername();

            Collection<SimpleGrantedAuthority> permList = (Collection<SimpleGrantedAuthority>) auth.getAuthorities();   
            List<String> permissions = new ArrayList<String>();

            for (SimpleGrantedAuthority authority : permList) {
                permissions.add(authority.getAuthority());
            }


            Query query = getMasterEntityManager()
                            .createNativeQuery(
                "SQL for retrieving the schema by the current logged in user");

            query.setParameter("username", username);
            List<Object[]> result = null; //query.getResultList();

            if(result != null) {
                logger.info("Interceptor: context set for " + username);
                Object[] userObj = result.get(0);

                getContext().getContextData().put("username", username);
                getContext().getContextData().put("schema_name",(String)userObj[1]);
            }
        }

        return ctx.proceed();
      }
    } 

그런 다음 엔티티 관리자를 빌드할 때 원하는 스키마를 설정할 수 있습니다.

언급URL : https://stackoverflow.com/questions/3211138/jpa-eclipselink-how-to-change-default-schema

반응형