JPA - EclipseLink - Как изменить схему по умолчанию - PullRequest
11 голосов
/ 09 июля 2010

Я программирую веб-приложение, используя weblogic и oracle. источник данных настраивается через JNDI с ограниченным пользователем базы данных, который может использовать DML в таблицах, но не может использовать DDL. Как вы можете догадаться, этот пользователь не является владельцем этих таблиц, но ему предоставлен доступ.

Допустим, он GUEST_USER

Приложение использует JPA + EclipseLink и уже определено множество сущностей. Я не хочу писать в каждом классе каждой сущности атрибут для изменения схемы. Я пробовал SessionCustomizer с этим кодом.

public class MyCustomizer implements SessionCustomizer{

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

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

Кажется, что-то неинициализировано, я получаю исключение нулевого указателя, я даже не уверен, что это способ изменить схему соединений перед их использованием. Любые образцы или идеи?

Заранее спасибо за помощь!

Ответы [ 3 ]

16 голосов
/ 09 июля 2010

Если все объекты используют одну и ту же схему, вы можете использовать файл сопоставления xml для определения схемы по умолчанию.

Нечто подобное должно работать (например, для JPA 2.0, измените расположение схемы на 1.0)

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>
4 голосов
/ 04 апреля 2015

Вы можете сделать это программно. Вы можете настроить значение схемы по умолчанию для каждого сеанса.

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());
0 голосов
/ 26 ноября 2015

Я использую EJB прямо перед запросом базы данных, поэтому с помощью Перехватчики Я могу установить схему в контексте 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();
      }
    } 

Затем, когда вы создаете менеджер сущностей, вы можете установитьсхема, которую вы хотите.

...