【问题标题】:Spring : 2 EntityManagerFactory in 1 transactionSpring:1 个事务中的 2 个 EntityManagerFactory
【发布时间】:2015-07-05 17:48:33
【问题描述】:

我想在同一个应用程序中访问两个数据库。对于每个数据库连接,我都有一个 EntityManagerFactory。
我的问题是:我不能在同一个事务中合并两个数据库中的两个实体。

有我的 beans.xml 文件:

    <context:component-scan base-package="com.example.testdatabase.business" />
    <context:component-scan base-package="com.example.testdatabase.service" />
    <context:component-scan base-package="com.example.testdatabase.ui" />

    <bean id="entityManagerFactoryOrder"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSourceOrder" />
        <property name="packagesToScan" value="com.example.testdatabase.business.order" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">validate</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="validationQuery">select 1 from dual</prop>
                <prop key="testOnBorrow">true</prop>
            </props>
        </property>
        <property name="persistenceUnitName" value="orderPU" />
    </bean>

    <bean id="dataSourceOrder" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:jboss/datasources/OrderCita" />
    </bean>

    <bean id="transactionManagerOrder" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactoryOrder" />
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
    </bean>

    <bean id="entityManagerFactoryPerson"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSourcePerson" />
        <property name="packagesToScan" value="com.example.testdatabase.business.person" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
        <property name="persistenceUnitName" value="personPU" />
    </bean>

    <bean id="dataSourcePerson" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:jboss/datasources/Person" />
    </bean>

    <bean id="transactionManagerPerson" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactoryPerson" />
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
    </bean>

    <tx:annotation-driven/>

我的仓库:

@Repository
public class Repo {

   @PersistenceContext(unitName="orderPU")
   @Qualifier(value="entityManagerFactoryOrder")
   protected EntityManager emOrder;

   @PersistenceContext(unitName="personPU")
   @Qualifier(value="entityManagerFactoryPerson")
   protected EntityManager emPerson;

   public void save() {
       Order o = new Order();
       o.setTheString("the order");

       emOrder.merge(o);
       emOrder.close();

       Person p = new Person();
       p.setTheString("the person");

       emPerson.merge(p);
       emPerson.close();
    }
}

我的服务:

@Service
public class Manager {
   @Autowired
   private Repo repo;

   @Transactional(value="transactionManagerOrder")
   public void save1() {
       repo.save();
   }

   @Transactional(value="transactionManagerPerson")
   public void save2() {
       repo.save();
   }

   @Transactional
   public void save3() {
       repo.save();
   }
}

方法“save1()”只合并一个订单。
方法“save2()”只合并一个人。
我想合并具有相同交易的订单和人员。

感谢您的帮助

PS : 对不起我的英语...


* 编辑 *
我尝试使用 bitronix,但现在出现了 nullpointerexception。
我还在 JpaProperties 中添加了这一行:
org.hibernate.engine.transaction.jta.p‌​latform.internal.BitronixJtaPlatform

这是我的新 beans.xml 文件:

    <bean class="bitronix.tm.TransactionManagerServices"
    factory-method="getConfiguration" id="bitronixConfiguration" />

<bean class="bitronix.tm.TransactionManagerServices" depends-on="bitronixConfiguration"
    destroy-method="shutdown" factory-method="getTransactionManager" id="bitronixTransactionManager" />

<bean class="bitronix.tm.resource.jdbc.PoolingDataSource"
    destroy-method="close" id="datasourceOrder" init-method="init">
    <property name="allowLocalTransactions" value="true" />
    <property name="className" value="org.postgresql.xa.PGXADataSource" />
    <property name="driverProperties">
        <props>
            <prop key="password">pwd</prop>
            <prop key="url">jdbc:postgresql://localhost:5432/order</prop>
            <prop key="user">user</prop>
        </props>
    </property>
    <property name="maxPoolSize" value="5" />
    <property name="minPoolSize" value="1" />
    <property name="uniqueName" value="exampleDS" />
</bean>

<bean class="bitronix.tm.resource.jdbc.PoolingDataSource"
    destroy-method="close" id="datasourcePerson" init-method="init">
    <property name="allowLocalTransactions" value="true" />
    <property name="className" value="org.postgresql.xa.PGXADataSource" />
    <property name="driverProperties">
        <props>
            <prop key="password">pwd</prop>
            <prop key="url">jdbc:postgresql://localhost:5432/person</prop>
            <prop key="user">user</prop>
        </props>
    </property>
    <property name="maxPoolSize" value="5" />
    <property name="minPoolSize" value="1" />
    <property name="uniqueName" value="sampleDS" />
</bean>

<bean id="entityManagerFactoryOrder"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jtaDataSource" ref="datasourceOrder" />
    <property name="packagesToScan" value="com.example.testdatabase.business.order" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.transaction.jta.platform">org.hibernate.engine.transaction.jta.p‌​latform.internal.BitronixJtaPlatform</prop>
            <prop key="hibernate.hbm2ddl.auto">validate</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="validationQuery">select 1 from dual</prop>
            <prop key="testOnBorrow">true</prop>
        </props>
    </property>
    <property name="persistenceUnitName" value="orderPU" />
</bean>

<bean id="entityManagerFactoryPerson"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jtaDataSource" ref="datasourcePerson" />
    <property name="packagesToScan" value="com.example.testdatabase.business.person" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.transaction.jta.platform">org.hibernate.engine.transaction.jta.p‌​latform.internal.BitronixJtaPlatform</prop>
            <prop key="hibernate.hbm2ddl.auto">create</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
    <property name="persistenceUnitName" value="personPU" />
</bean>

<bean class="org.springframework.transaction.jta.JtaTransactionManager"
    id="transactionManager">
    <property name="transactionManager" ref="bitronixTransactionManager" />
    <property name="userTransaction" ref="bitronixTransactionManager" />
</bean>

<tx:annotation-driven />

在 Manager 类中,我删除了 @Transactional 注释。
在 Repo 类中,我删除了@Qualifier 注解。

堆栈跟踪:

00:47:22,665 SEVERE [com.vaadin.server.DefaultErrorHandler] (http-localhost/127.0.0.1:8080-2) : java.lang.NullPointerException
at org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory.isJoinableJtaTransaction(CMTTransactionFactory.java:63) [hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory.isJoinableJtaTransaction(CMTTransactionFactory.java:39) [hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.isTransactionJoinable(TransactionCoordinatorImpl.java:295) [hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1205) [hibernate-entitymanager-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:178) [hibernate-entitymanager-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.ejb.EntityManagerImpl.<init>(EntityManagerImpl.java:89) [hibernate-entitymanager-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:179) [hibernate-entitymanager-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:174) [hibernate-entitymanager-4.1.9.Final.jar:4.1.9.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [rt.jar:1.6.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_45]
at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_45]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:376) [spring-orm-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:519) [spring-orm-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at com.sun.proxy.$Proxy38.createEntityManager(Unknown Source)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactoryUtils.java:202) [spring-orm-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:211) [spring-orm-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at com.sun.proxy.$Proxy40.merge(Unknown Source)
at com.example.testdatabase.business.repo.Repo.save(Repo.java:29) [classes:]
at com.example.testdatabase.service.Manager.save3(Manager.java:26) [classes:]
at com.example.testdatabase.service.Manager$$FastClassBySpringCGLIB$$3df77bc4.invoke(<generated>) [spring-core-4.1.6.RELEASE.jar:]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) [spring-core-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) [spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) [spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) [spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at com.example.testdatabase.service.Manager$$EnhancerBySpringCGLIB$$ab725425.save3(<generated>) [spring-core-4.1.6.RELEASE.jar:]
at com.example.testdatabase.TestdatabaseUI$3.buttonClick(TestdatabaseUI.java:56) [classes:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [rt.jar:1.6.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_45]
at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_45]
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:198) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:161) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:995) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.ui.Button.fireClick(Button.java:393) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.ui.Button$1.click(Button.java:61) [vaadin-server-7.5.0.jar:7.5.0]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [rt.jar:1.6.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_45]
at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_45]
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:158) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:118) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:313) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:202) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:95) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1408) [vaadin-server-7.5.0.jar:7.5.0]
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:350) [vaadin-server-7.5.0.jar:7.5.0]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.2.Final-redhat-1.jar:1.0.2.Final-redhat-1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169) [jboss-as-web-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:145) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:336) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:920) [jbossweb-7.2.2.Final-redhat-1.jar:7.2.2.Final-redhat-1]
at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_45]

【问题讨论】:

    标签: java spring hibernate entitymanager


    【解决方案1】:

    您目前正在使用本地事务管理器,它一次只针对一个数据存储管理事务。为了管理跨多个数据存储的事务,您需要一个符合 JTA 的事务管理器。

    请参阅 this sample app 以获取将 Bitronix JTA 事务管理器与 2 个 EntityManagers 一起使用的示例。

    【讨论】:

    • 我尝试了一些东西,但它不起作用。我在我的问题中添加了详细信息。
    • 似乎 Hibernate EntityManager 无法加入 JTA 事务。在每个 EntityManager bean 的 jpaProperties 下,尝试添加 &lt;prop name="hibernate.transaction.jta.platform"&gt;org.hibernate.engine.transaction.jta.platform.internal.BitronixJtaPlatform&lt;/prop&gt;
    • 我仍然有一个 nullPointerException 但有点不同。我再次更新了我的问题(在“编辑”部分下)。信息:System.out.println("em : " + emOrder);告诉我em : Shared EntityManager proxy for target factory [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@5ad8def2]
    • 你需要稍微调试一下。请参阅another sample app,我在其中添加了带有两个 Postgres 实例(您的场景)的 Bitronix 配置,它工作正常(单元测试可能需要很长时间才能运行,但它们运行成功)。我看到你的配置的唯一区别是我也有&lt;prop key="javax.persistence.transactionType"&gt;jta&lt;/prop&gt;。看看是否有帮助。如果没有,您可以从我发现更易于使用的同一文件中尝试 Atomikos 配置。
    • 在 bean 定义文件中,我添加了这个,并删除了所有 Bitronix 和 Atomikos :&lt;bean id="transactionManager" class="org.springframework.data.transaction.ChainedTransactionManager"&gt; &lt;constructor-arg&gt; &lt;list&gt; &lt;ref bean="transactionManagerOrder"/&gt; &lt;ref bean="transactionManagerPerson"/&gt; &lt;/list&gt; &lt;/constructor-arg&gt; &lt;/bean&gt; 它似乎工作......这很奇怪......这太简单了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多