In spring, what code is used to inject the value for the @PersistenceContext annotated variables?
Using a ClassPathXmlApplicationContext object I want to get the same EntityManager that is being used by other parts of the app开发者_如何学JAVA which get it injected via:
@PersistenceContext(unitName="accessControlDb") private EntityManager em;
Using ctx.getBean("access-emf") I can get the EntityManagerFactory which is defined in the applicationContext.xml. Using that I can create a new EntityManager, but I can't get the existing EntityManager used by the rest of the app.
I just can't figure out what code is executed to inject the value for the @PersistenceContext annotation.
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
<bean id="innerNgsdpDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource">
<property name="driverName" value="${ngsdp.jdbc.driver}"/>
<property name="url" value="${ngsdp.jdbc.url}"/>
<property name="user" value="${ngsdp.jdbc.username}"/>
<property name="password" value="${ngsdp.jdbc.password}"/>
<property name="transactionManager" ref="jotm"/>
</bean>
<bean id="ngsdpDataSource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource">
<property name="transactionManager" ref="jotm"/>
<property name="dataSource" ref="innerNgsdpDataSource"/>
<property name="user" value="${ngsdp.jdbc.username}"/>
<property name="password" value="${ngsdp.jdbc.password}"/>
<property name="maxSize" value="4"/>
<property name="checkLevelObject" value="2"/>
<property name="jdbcTestStmt" value="select 1 from dual"/>
</bean>
<bean id="myEmf" name="moservices" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="ngsdpDataSource"/>
<property name="persistenceXmlLocation" value="WEB-INF/moservices-persistence.xml" />
<property name="jpaVendorAdapter" ref="hibernate_jpa_vendor_adapter" />
<property name="jpaPropertyMap" ref="jpa_property_map"/>
<property name="jpaDialect" ref="hibernate_jpa_dialect"/>
</bean>
If using spring-managed transactions, you can get the current EntityManager
by calling
EntityManagerFactory emFactory = ctx.getBean("access-emf");
EntityManagerHolder emHolder =
(EntityManagerHolder) TransactionSynchronizationManager.getResource(emFactory);
EntityManager em = emHolder.getEntityManager();
This is most often the current EntityManager
. But this is something which should be avoided (except possibly in unit-tests), as stated in the spring docs:
To be used by resource management code but not by typical application code
Another approach might be to intercept your service calls using Spring AOP, inject the @PersistenceContext
in the advice, and set in in a ThreadLocal
of yours. Later, you can get it from that ThreadLocal
.
精彩评论