spring - 能够在应用程序中动态切换持久性单元 (JPA)

标签 spring jpa eclipselink

我的应用程序数据访问层是使用 Spring 和 EclipseLink 构建的,我目前正在尝试实现以下功能 - 能够为用户动态切换当前/事件的持久性单元。我尝试了各种选择,最后做了以下事情。

在persistence.xml 中,声明多个PU。创建一个具有与定义的 PU 一样多的 EntityManagerFactory 属性的类。这将充当工厂并根据我的逻辑返回适当的 EntityManager

public class MyEntityManagerFactory {
  @PersistenceUnit(unitName="PU_1")
  private EntityManagerFactory emf1;

  @PersistenceUnit(unitName="PU_2")
  private EntityManagerFactory emf2;

  public EntityManager getEntityManager(int releaseId) {
    // Logic goes here to return the appropriate entityManeger
 }
}

我的 spring-beans xml 看起来像这样..
<!--  First persistence unit  -->    
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="emFactory1">
  <property name="persistenceUnitName" value="PU_1" />
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager1">
  <property name="entityManagerFactory" ref="emFactory1"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager1"/>

对于第二个 PU(名称如 emFactory2、transactionManager2 等)重复上述部分。

我是 JPA 新手,我知道这不是最好的解决方案。我感谢以更好/优雅的方式实现此要求的任何帮助!

谢谢!

最佳答案

首先感谢 user332768 和 bert。我尝试使用bert提供的链接中提到的AbstractRoutingDataSource,但在尝试连接我的jpa层(eclipselink)时迷路了。我通过一些修改恢复了我的旧方法。该解决方案看起来更干净(恕我直言)并且工作正常。 (在运行时切换数据库并在同一事务中写入多个数据库)

public class MyEntityManagerFactoryImpl implements MyEntityManagerFactory, ApplicationContextAware {

    private HashMap<String, EntityManagerFactory> emFactoryMap;

    public EntityManager getEntityManager(String releaseId) {
        return SharedEntityManagerCreator.createSharedEntityManager(emFactoryMap.get(releaseName));
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        Map<String, LocalContainerEntityManagerFactoryBean> emMap = applicationContext.getBeansOfType(LocalContainerEntityManagerFactoryBean.class);
        Set<String> keys = emMap.keySet();
        EntityManagerFactory entityManagerFactory = null;
        String releaseId = null;
        emFactoryMap = new HashMap<String, EntityManagerFactory>();
        for (String key:keys) {
            releaseId = key.split("_")[1];
            entityManagerFactory = emMap.get(key).getObject();
            emFactoryMap.put(releaseId, entityManagerFactory);
        }
    }
}

我现在用 MyEntityManagerFactoryImpl 的一个实例(单例)注入(inject)我的 DAO。然后,dao 将简单地使用所需的版本调用 createSharedEntityManager,并为该数据库获取正确的 EntityManager。 (请注意,我现在正在使用应用程序管理的 EntityManager,因此我必须在我的 dao 中明确关闭它们)

我还搬到了 jta 事务管理器(管理跨多个数据库的事务)
这就是我的 spring xml 现在的样子。
...
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="em_Rel1">
        <property name="persistenceUnitName" value="PU1" />
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="em_Rel2">
        <property name="persistenceUnitName" value="PU2" />
</bean>

<bean class="org.springframework.transaction.jta.JtaTransactionManager" id="jtaTransactionManager">
</bean>
<tx:annotation-driven transaction-manager="jtaTransactionManager"/>
....

干杯! (欢迎评论)

关于spring - 能够在应用程序中动态切换持久性单元 (JPA),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2765631/

相关文章:

java - EclipseLink/JPA : Specify length of byte array

java - 如何使用 WebServiceTemplate 发送 SOAP 请求?

java - 删除不使用 JpaRepository

java - 使用默认模板的 spring mvc 出现 404 错误

java - Spring Data JPA – 自定义 native 查询方法列表打印 java.lang.Object

java - 多个线程访问数据库 : one with long transaction, 一个带有短事务

javax.ejb.TransactionRolledbackLocalException : Exception thrown from bean

java - EclipseLink 如何从 ManyToOne 关系中的 "one side"中删除孤立实体

java - Singleton bean 中的请求作用域字段

java - Spring hibernate 事务