我需要一种在 EJB 中动态指定持久性单元的方法。
简化示例:
我有一个使用多个数据库作为数据存储的应用程序。
每个数据存储在结构上都是相同的。
根据连接到应用程序的客户端,我需要从中访问数据
特定的数据存储。
因此,我想使用相同的EJB,这样业务逻辑就不会重复,
但随后只需根据客户端选择正确的持久性单元。
到目前为止,我只是直接将持久性单元名称硬编码注入(inject)实体管理器。
有没有一种方法可以动态注入(inject)实体管理器,并将所需的持久性单元附加到 EJB?
此外,可以在运行时动态添加持久性单元吗?
我目前必须在 persistence.xml 文件中指定持久性单元。
理想情况下,我想在系统运行时根据需要在服务器 jdbc/db1、jdbc/db2 等上创建池。然后只需将这些添加到中央客户端数据库并将其链接到客户端,这样当客户端连接时,它会检查池的名称,并在调用 EJB 时使用它来获取持久性单元。
我对 Java EE 开发仍然很陌生。任何帮助将不胜感激。
最佳答案
在当前的 JPA 版本中,很遗憾无法动态创建持久性单元。如果此功能对您很重要,您可以考虑在 JPA 问题跟踪器中为其创建 JIRA 问题:http://java.net/jira/browse/JPA_SPEC
使用 @PersistenceContext
注释,也无法动态选择特定的持久性单元。这实际上是分片的领域,Hibernate 曾经试图解决这个问题,但后来突然停止了。见 http://www.hibernate.org/subprojects/shards.html
但是,您可以做一些事情来获得类似的效果。
一种方法是创建一个无状态 EJB/CDI 工厂 bean,将其注入(inject)所有实体管理器。这样做的成本是微不足道的,因为这些 bean 将被汇集起来,而且实体管理器的创建成本并不高。
如果您还想根据某些条件注入(inject)它们,那么这个条件必须从上下文中可用或必须在注入(inject)点指定(但如果您愿意这样做,您也可以注入(inject)正确的实体管理器直接地)。
开球示例:
@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;
}
}
}
然后在你的 bean 里:
@Stateless
public class SomeBean {
@Inject @ShardedPersistenceContext
private EntityManager entityManager;
// ...
}
请注意,
@TransactionScoped
此处需要 Seam Persistence。注解。忘记透明地注入(inject)实体管理器并注入(inject) ShardingEntityManagerFactory
也可能更容易,但更冗长一些。而是手动从中获取正确的。
关于jakarta-ee - JPA 动态持久化单元名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9957179/