JPA动态持久化单元名称

lik*_*her 15 jpa java-ee ejb-3.1

我需要一种方法来动态指定EJB中的持久性单元.

简化示例:

我有一个应用程序使用多个数据库作为数据存储.每个数据存储在结构上都是相同的.根据连接到应用程序的客户端,我需要访问特定数据存储中的数据.

因此,我想使用相同的EJB,以便不重复业务逻辑,但只需根据客户端选择正确的持久性单元.

到目前为止,我只是直接向实体管理器注入硬编码的持久性单元名称.有没有办法可以动态地为实体管理器注入附加到EJB的所需持久性单元?此外,可以在运行时动态添加持久性单元吗?我目前必须在persistence.xml文件中指定持久性单元.理想情况下,我想在系统运行时根据需要在服务器jdbc/db1,jdbc/db2等上创建池.然后将这些添加到中央客户端数据库并将其链接到客户端,以便在客户端连接时,它将检查池的名称,并在调用EJB以获取持久性单元时使用它.

我还是Java EE开发的新手.任何帮助将不胜感激.

Arj*_*jms 8

在当前的JPA版本中,遗憾的是无法动态创建持久性单元.如果此功能对您很重要,您可以考虑在JPA问题跟踪器上为它创建一个JIRA问题:http://java.net/jira/browse/JPA_SPEC

使用@PersistenceContext注释,也无法动态选择特定的持久性单元.这实际上是分片的领域,Hibernate曾试图解决但后来突然停止了.见http://www.hibernate.org/subprojects/shards.html

然而,你可以采取一些措施来获得类似的效果.

一种方法是创建一个无状态EJB/CDI工厂bean,您可以使用所有实体管理器注入它.这种成本是微不足道的,因为这些bean将被合并,而实体经理并不是首先要创建的.

如果你还想根据某些条件注入它们,那么这个条件必须从上下文中获得,或者必须在注入点指定(但如果你这样做,你也可以注入正确的实体管理器)直).

启动示例:

@Stateless
@TransactionAttribute(SUPPORTS)
public class ShardingEntityManagerFactory {

    @Resource
    private SessionContext sessionContext;

    @PersistenceContext(unitName = "pu1")
    private EntityManager entityManager1;

    @PersistenceContext(unitName = "pu2")
    private EntityManager entityManager2;

    @Produces @TransactionScoped @ShardedPersistenceContext
    public EntityManager getEntityManager() {
        if (sessionContext.isCallerInRole("FOO")) {
            return entityManager1;
        } else {
            return entityManager2;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的豆子里:

@Stateless
public class SomeBean {

    @Inject @ShardedPersistenceContext
    private EntityManager entityManager;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,此处需要Seam Persistence作为@TransactionScoped注释.忘记透明地注入实体管理器并注入ShardingEntityManagerFactory而不是手动从中获取正确的实体管理器也可能更容易,但更冗长一点.