Consider having two entity manager factories:
<bean id="writeEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">...</bean> <bean id="readOnlyEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">...</bean>
Then I want to have two Beans to which I would inject the correct persistence context:
<bean id="readOnlyManager" class="..MyDatabaseManager"> <bean id="writeManager" class="..MyDatabaseManager">
The bean would look something like:
public class MyDatabaseManager { private javax.persistence.EntityManager em; public EntityManager(javax.persistence.EntityManager em) { this.em = em; } ... }
This obviously doesn't work, because EntityManager is not a bean and cannot be injected in this way:
No qualifying bean of type 'javax.persistence.EntityManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
How can I qualify correct EntityManager in the bean? I used to use @PersistenceContext
annotation, but this is not usable as I need to inject it.
How can I specify the PersistenceContext for such Bean?
UPDATE: My question is how to inject PersistenceContext with qualifier via XML, not via annotation.
2 Answers
Answers 1
Assuming that you are using spring in order to manage transactions what I would do is 2 different transaction managers and then in my services i would use the most appropriate transaction manager like this:
Configuration section
@Bean public LocalContainerEntityManagerFactoryBean writeEntityManagerFactory() { LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); //Your configuration here return factory; } @Bean(name={"writeTx"}) public PlatformTransactionManager writeTransactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(writeEntityManagerFactory().getObject()); return txManager; } @Bean public LocalContainerEntityManagerFactoryBean readEntityManagerFactory() { LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); //Your configuration here return factory; } @Bean(name={"readTx"}) public PlatformTransactionManager readTransactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(readEntityManagerFactory().getObject()); return txManager; }
Service layer
@Transactional(value="readTx") public List<Object> read(){ //Your read code here } @Transactional(value="writeTx") public void write(){ //Your write code here }
UPDATED ANSWER I misunderstood the question.
In your configuration class you can define:
@Bean public LocalContainerEntityManagerFactoryBean writeEntityManagerFactory() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); em.setPackagesToScan(new String[] { "models" }); JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); em.setJpaProperties(hibProps()); em.setPersistenceUnitName("writer"); return em; } @Bean public LocalContainerEntityManagerFactoryBean readEntityManagerFactory() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); em.setPackagesToScan(new String[] { "models" }); JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); em.setJpaProperties(hibProps()); em.setPersistenceUnitName("reader"); return em; }
Please see the PersistenceUnitName
values
Then you can injecting them by doing:
@PersistenceContext(unitName="writer") private EntityManager emWriter; @PersistenceContext(unitName="reader") private EntityManager emReader;
I just tested it and all worked pretty good
Angelo
Answers 2
persistence.xml (2 persistence unit for 2 different entitymanager, based on your persistence provider here i ma using HibernatePersistence)
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="pu1"> <provider>org.hibernate.ejb.HibernatePersistence</provider> </persistence-unit> <persistence-unit name="pu2"> <provider>org.hibernate.ejb.HibernatePersistence</provider> </persistence-unit> </persistence>
Make sure you are assigning the persistence-unit to entity manager using property persistenceUnitName
<bean id="writeEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceXmlLocation" value="classpath: of yout persistence xml" /> <property name="persistenceUnitName" value="pu1" /> .....other configuration of em.. </bean>
same for other em.
Now, use constructor injection for MyDatabaseManager to inject EntityManager (using qualifier name ex. writeEntityManagerFactory )
<bean id="mdm" class="MyDatabaseManager"> <constructor-arg ref = "writeEntityManagerFactory"/> </bean>
0 comments:
Post a Comment