【问题标题】:How can I specify which entity manager factory to use, without modifying the DAO class?如何在不修改 DAO 类的情况下指定要使用的实体管理器工厂?
【发布时间】:2020-06-05 02:04:38
【问题描述】:

我有一个 Java 7 / Spring 3.2.17 应用程序,它必须连接到两个不同的数据库,所以我有两个不同的 persistence.xml 文件,每个文件都声明了自己的持久性单元。

在我的应用程序上下文中,我定义了两个实体管理器工厂,例如:

<bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="myDatasource1" />
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence1.xml" />
    <property name="persistenceUnitName" value="pu1" />
    ...
</bean>

在我的 DAO 类中,我只是让 Spring 注入实体管理器:

@PersistenceContext
private EntityManager entityManager;

public void setEntityManager (...) { ... }

Spring 抱怨我有两个 EM 工厂,所以它不知道该使用哪一个:

NoUniqueBeanDefinitionException:没有定义类型 [javax.persistence.EntityManagerFactory] ​​的合格 bean:预期单个匹配 bean,但找到 2:emf1,emf2

我已经通过specifying which persistence unit I want to use部分解决了,像这样:

@PersistenceContext(unitName = "pu1")
private EntityManager entityManager;

public void setEntityManager (...) { ... }

这解决了类连接到第一个数据库的问题。我的问题是其他数据库的类是第三方库的一部分,所以我无法修改它们以添加 unitName 属性。 我还有其他方法可以做到吗?


我尝试了几个选项,但所有选项都会导致相同的错误消息:

  1. 扩展类以便我可以“覆盖注释”
public class MyDao extends TheDaoThatICannotModify {
    @Override
    @PersistenceContext(unitName = "pu2")
    public void setEntityManager (EntityManager em) {
        super.setEntityManager(em);
    }
}
  1. 实例化 EM 并自己注入:
<bean id="entityManager2" factory-bean="emf2" factory-method="getObject" />

<bean id="myDao" class="com.foo.TheDaoThatICannotModify">
    <property name="entityManager" ref="entityManager2" />
</bean>
  1. primary="true" 属性添加到我的emf2 bean(和primary="false"emf1)。

  2. autowire-candidate="false" 属性添加到我的emf1 bean。

【问题讨论】:

    标签: java spring entitymanager


    【解决方案1】:

    我得到了它的工作...通过仅对我自己的类使用 Spring 注入,并将 EM 传递给 evil DAO 我自己:

    public class MyDaoSingletonFactoryIsh {
        @PersistenceContext(unitName = "pu2")
        private EntityManager em; // Injected by Spring
    
        private static TheDaoThatICannotModify dao = null;
    
        public TheDaoThatICannotModify getDAO() {
            if (dao == null) {
                dao = new TheDaoThatICannotModify();
                dao.setEntityManager(em);
            }
            return dao;
        }
    }
    

    我不知道如何调用这种模式:工厂、单例、包装器?它并不真正适合这些类别中的任何一个,它是它们的奇怪组合。这可能不是一个好兆头,它看起来像是一种巨大的代码气味,我宁愿避免它。但至少它是有效的,所以缺乏更好的解决方案......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多