1

JPA 是否支持可选的持久性单元,如果支持,我该如何配置?

我确实有一个持久性单元,它是我的主数据库。

然后我配置了另一个,我只是从数据库中读取对象来做一些检查。为了避免弄乱多个数据源上的事务,我设置了第二个数据源jta="false"

但是我希望能够检查是否定义了第二个数据源,并且只有在它存在时才使用它。如果未定义,我想简单地跳过我的检查。

问题是我找不到如何使它成为可选的。如果没有配置第二个数据源,我会New missing/unsatisfied dependencies在部署我的战争时从 Jboss 中的部署扫描器中收到错误消息:

service jboss.naming.context.java.secondDatasource (missing) dependents: [service jboss.persistenceunit."de.my.war#secondDatasource"] 

(顺便说一句:我正在使用 JBoss 7.1.0 并在 standard.xml 中配置了数据源 - 如果该信息有任何相关性。)

有什么提示吗?

4

2 回答 2

4

我不确定 XML 配置是否可行,这基本上是在大多数情况下应如何使用 JPA 的约定。尝试寻找一种程序化的方法。

也许您可以以编程方式将数据源查找为 JNDI 资源,如果找到,您可以自己构建一个 EntityManager在CDI的帮助下,它甚至可能没有您想象的那么困难。

@Produces
@MyAlterNativeEntityManager
public EntityManager getEntityManager {
    EntityManager entityManager = null;
    if(jndiLookupMySecondDatasource()){
       entityManager = buildEntityManagerProgrammatically(...);
    }
    return entityManager;
}

当然,如果找不到数据源,则会返回一个空的 EntityManager,但是在调用代码中,您可以简单地检查它是否已初始化并仅在初始化时使用。希望这有助于使您走上正确的道路。

于 2013-03-06T12:30:00.410 回答
1

在 JPA 标准中:

  • 每个 EntityManagerFactory (EMF) 必须与一个 PersistentUnit (PU) 相关 - 不可能有多个 PersistenceUnits 也不可能有零个 PersistenceUnits。
  • 每个 EntityManager (EM) 实例都是从 EMF 创建的,因此也有一个 PU。当然,可以从一个 EMF 创建多个 EM,所有这些都使用相同的 PU。
  • 可以使用硬编码配置针对每个 EMF 显式使用的 PU

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("EmployeeService");

    或通过使用注释注入 EMF

    @PersistenceUnit("EmployeeService") EntityManagerFactory 电动势;

    或者可以将其留空,只需选择在 persistence.xml 中配置的默认 PU。

  • 可以通过使用注解注入 EM 来配置对每个 EM 显式使用的 PU。这里的代码根本没有引用 EMF(让容器不可见地引用 EMF)

    @PersistenceContext(unitName="EmployeeService") EntityManager em;

在所有这些中,可选 PU 的想法没有任何意义。如果您使用的是 JPA EM,则必须提交到 PU。

选项:

  1. 编辑 persistence.xml 以在两个不同的物理数据库实例之间具有相同的逻辑持久性单元“切换”。不满足全部要求 - 仍会从替代数据源读取值。
  2. 根据 Balazs Maria Nemeth 的解决方案,查找/注入环境变量(“调试”与否)并以编程方式在不同的数据源之间切换。不满足全部要求,因为它仍会从备用数据源读取值。
  3. 查找/注入环境变量(“调试”与否)并适当地为您的替代 EM 运行/排除代码。

3 是唯一满足全部要求的选项。例如:

// Inject environment setting. Resource annotation works with/without CDI -  
// just doesn't give scoping support, which isn't required here.
@Resource boolean debugMode;

if (debugMode) {
    @PersistenceContext(unitName="DebugPersistenceUnit")
    EntityManager debugEM;

    Employee emp = debugEM.find(Employee.class, empId);
}

然后在您的 web.xml 或 ejb.xml 中包含一个 env-entry:

<env-entry>
    <description>
     Only set this true in a debugging environment
    </description>
    <env-entry-name>debugMode</env-entry-name>
    <env-entry-type>java.lang.Boolean</env-entry-type>
    <env-entry-value>true</env-entry-value>
</env-entry>
于 2013-03-11T02:28:08.677 回答