I have a Java 7 / Spring 3.2.17 application which has to connect to two different databases, so I have two different persistence.xml files, each one declaring its own persistence unit.
In my application context I have defined two entity manager factories, such as:
<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>
And in my DAO classes I just let Spring inject the entity manager:
@PersistenceContext
private EntityManager entityManager;
public void setEntityManager (...) { ... }
Spring complains that I have two EM factories so it doesn't know which one to use:
NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: emf1,emf2
I have partially solved it by specifying which persistence unit I want to use, like this:
@PersistenceContext(unitName = "pu1")
private EntityManager entityManager;
public void setEntityManager (...) { ... }
That solved the problem for the classes connecting to the first database. My problem is that the classes for the other DB are part of a third-party library, so I can't modify them to add the unitName
attribute. Is there any other way I can do it?
I have tried a few options, but all of them lead to the same error message:
public class MyDao extends TheDaoThatICannotModify {
@Override
@PersistenceContext(unitName = "pu2")
public void setEntityManager (EntityManager em) {
super.setEntityManager(em);
}
}
<bean id="entityManager2" factory-bean="emf2" factory-method="getObject" />
<bean id="myDao" class="com.foo.TheDaoThatICannotModify">
<property name="entityManager" ref="entityManager2" />
</bean>
Adding the primary="true"
attribute to my emf2
bean (and primary="false"
to emf1
).
Adding the autowire-candidate="false"
attribute to my emf1
bean.
I got it working... by using Spring injection only with my own classes, and passing the EM to the evil DAOs myself:
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;
}
}
I don't know how to call this pattern: factory, singleton, wrapper? It doesn't really fit in any of these categories, it's a weird combination of them. Which isn't probably a good sign, it looks like a huge code smell and I'd prefer to avoid it. But at least it's working, so, lacking of a better solution...