JPA中的可选持久性单元(使用多个持久性单元时)

时间:2013-03-01 10:28:06

标签: java-ee jpa java-ee-6 jndi persistence-unit

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

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

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

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

问题是我找不到如何使这个可选。如果未配置第二个数据源,则在部署战争时,Jboss中的部署扫描程序会出现New missing/unsatisfied dependencies错误:

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

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

任何提示?

2 个答案:

答案 0 :(得分:4)

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

也许您可以以编程方式将数据源作为JNDI资源进行查找,如果找到了一个,您可以自己build an EntityManager。在CDI的帮助下,它甚至可能不像您想象的那么困难。

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

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

答案 1 :(得分:1)

在JPA标准中:

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

    EntityManagerFactory emf = Persistence.createEntityManagerFactory(“EmployeeService”);

    或使用注释注入EMF

    @PersistenceUnit( “的EmployeeService”) EntityManagerFactory emf;

    或者可以将其留空,只需选择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的代码。
  4. 3只是满足全部要求的选项。 E.g:

    // 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>