如何在@PersistenceContext中动态修改unitName

时间:2015-11-18 21:36:06

标签: jpa ejb persistence cdi entitymanager

我使用的是JPA 2.1,我有类似这样的事情

public class EntityManagerProducer {
    @Produces
    @PersistenceContext(unitName="first_PU")
    private EntityManager em;
    ...

如何动态修改unitName中的@PersistenceContext(unitName = "somer_PU")以使用其他实体管理器?这可能吗?

  

非常重要的更新

我有一个已部署的应用程序,persistence.xml看起来像这样:

<persistence-unit name="db1" transaction-type="JTA">
<jta-data-source>java:/jboss/datasources/PostgresDS</jta-data-source>
<properties>
  <property name="hibernate.hbm2ddl.auto" value="update"/>
  <property name="hibernate.show_sql" value="true"/>
  <property name="hibernate.format_sql" value="true"/>
  <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
  <property name="hibernate.cache.use_second_level_cache" value="false"/>
  <property name="hibernate.jdbc.batch_size" value="50"/>
  <property name="hibernate.jdbc.batch_versioned_data" value="true"/>
  <property name="hibernate.order_inserts" value="true"/>
  <property name="hibernate.order_updates" value="true"/>
  <property name="hibernate.generate_statistics" value="true"/>
  <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
  <property name="jboss.entity.manager.jndi.name" value="java:app/entitymanager/db1"/>
  <property name="jboss.entity.manager.factory.jndi.name" value="java:app/entitymanagerfactory/db1"/>
</properties>

在运行时,可以修改persistence.xml并添加另一个持久性单元,但我需要一种方法来通过传递持久性单元的名称来获取我需要的实体管理器,然后将其用于我想要的内容。然后我可以提供另一个持久性单元的名称,并获得一个不同的实体管理器。当然,我希望交易流程仍然是容器管理

2 个答案:

答案 0 :(得分:6)

请相信我,您不想修改现有unitName内的PersistenceContext。我几乎可以肯定,你想要实现的只是让第二个EntityManager指向另一个数据库,对吗?

然后一个自然的方法是:

public class SomeClass {

    @PersistenceContext(unitName = "first_PU")
    EntityManager firstEntityManager;

    @PersistenceContext(unitName = "somer_PU")
    EntityManager secondEntityManager;

    // ...
}

个人建议

  1. 请注意,使用EJB时​​,您不必为EntityManager创建Producer方法,因为键入@PersistenceContext(...)就足够了。

  2. 强烈建议不要跟随:

    @Produces
    @PersistenceContext(unitName="first_PU")
    private EntityManager em;
    

    因为默认范围是@Dependent。更好的是@RequestScoped@TransactionScoped

  3. 您可以使用CDI和注释限定符代替硬编码的单位名称:

    @Inject
    private @FirstDB EntityManager firstEntityManager;
    
    @Inject
    private @SecondDB EntityManager secondEntityManager;
    

    但是你需要:

    @Produces
    @RequestScoped // or other
    @FirstDB
    public EntityManager createEntityManagerA() {
        return firstEmf.createEntityManager();
    }
    
    @Produces
    @RequestScoped  // or other
    @SecondDB
    public EntityManager createEntityManagerB() {
        return secondEmf.createEntityManager();
    }
    
  4. 有关CDI和生成多个EntityManagers的大量有用信息,您可以找到here

答案 1 :(得分:0)

这是不可能的。如果需要动态持久性单元名称,则需要完全避免EE集成并直接使用javax.persistence.Persistence类,但我不建议这样做。作为替代方案,您可以为所有持久性单元注入EntityManager / Factory,然后使用switch语句或类似方法选择正确的那个。