JPA – EclipseLink – 如何更改默认架构

我正在使用weblogic和oracle编写Web应用程序。 数据源是通过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"); } } 

似乎有一些未初始化的东西,我得到一个空指针exception,我甚至不确定这是否是在使用它们之前更改连接的模式的方法。 任何样品或想法?

在此先感谢您的帮助!

如果所有实体都使用相同的模式,则可以使用xml映射文件来定义默认模式。

这样的东西应该工作(例如,对于JPA 2.0,更改1.0的schemaLocation)

orm.xml中:

    OWNERS_SCHEMA   . . .  

persistence.xml中:

   . . . orm.xml . . .   

你可以以编程方式完成。 您可以为每个会话配置默认架构值。

 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 ,因此通过使用Interceptor,我可以通过查看当前经过身份validation的用户来设置EJB上下文中的模式。

然后,当我构建实体管理器时,我可以设置正确的架构。 通过这种方式,通过不在表名之前指定模式,PostgreSQL将查看search_path以确定要查询的模式。

  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 permList = (Collection) auth.getAuthorities(); List permissions = new ArrayList(); 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 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(); } } 

然后,在构建实体管理器时,可以设置所需的架构。