Данные Spring - два разных источника данных в одной транзакции, вызывающие отклонения

Мы используем Atomikos JTA с пружиной и 2 разных источника данных MySQL.

Мы столкнулись с проблемой,

Когда мы используем два разных репозитория (из 2 разных источников данных) для одного и того же метода @Transactional, мы получаем ошибку:

Caused by: java.sql.SQLException: Unable to enlist connection the transaction

Это происходит, когда второй репозиторий выполняет какие-либо действия с источником данных.

Мы считаем, что это как-то связано с менеджером транзакций (atomikos jta), который может иметь проблемы, когда в одной транзакции участвуют 2 разных источника данных.

Вот источники данных XML:

    <bean
    class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<bean id="xaDataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
    lazy-init="true">
    <property name="pinGlobalTxToPhysicalConnection" value="true" />
    <property name="url" value="${mysql_url}" />
    <property name="user" value="root" />
    <property name="password" value="xxx" />
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.managed.BasicManagedDataSource">
    <property name="initialSize" value="10" />
    <property name="maxActive" value="100" />
    <property name="maxIdle" value="15" />
    <property name="minIdle" value="10" />
    <property name="timeBetweenEvictionRunsMillis" value="10000" />
    <property name="minEvictableIdleTimeMillis" value="60000" />
    <property name="validationQuery" value="/* ping */ SELECT 1" />
    <property name="testOnBorrow" value="true" />
    <property name="testWhileIdle" value="true" />
    <property name="xaDataSourceInstance" ref="xaDataSource" />
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="removeAbandoned" value="true" />
    <property name="removeAbandonedTimeout" value="300" />
</bean>

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="packagesToScan" value="com.xxx.model" />
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource" />
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="database" value="MYSQL" />
            <property name="showSql" value="false" />
            <property name="generateDdl" value="false" />
        </bean>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="javax.persistence.transactionType" value="JTA" />
            <entry key="hibernate.transaction.manager_lookup_class"
                value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup" />
            <entry key="hibernate.connection.autocommit" value="false" />
        </map>
    </property>
</bean>

<!-- shared data source -->

<bean id="shardXaDataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
    lazy-init="true">
    <property name="pinGlobalTxToPhysicalConnection" value="true" />
    <property name="url" value="${shared_mysql_url}" />
    <property name="user" value="root" />
    <property name="password" value="xxx" />
</bean>

<bean id="shareddDataSource" class="org.apache.commons.dbcp.managed.BasicManagedDataSource">
    <property name="initialSize" value="10" />
    <property name="maxActive" value="100" />
    <property name="maxIdle" value="15" />
    <property name="minIdle" value="10" />
    <property name="timeBetweenEvictionRunsMillis" value="10000" />
    <property name="minEvictableIdleTimeMillis" value="60000" />
    <property name="validationQuery" value="/* ping */ SELECT 1" />
    <property name="testOnBorrow" value="true" />
    <property name="testWhileIdle" value="true" />
    <property name="xaDataSourceInstance" ref="shardXaDataSource" />
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="removeAbandoned" value="true" />
    <property name="removeAbandonedTimeout" value="300" />
</bean>

<bean id="sharedEntityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="packagesToScan" value="com.xxx.shared.model" />
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        </props>
    </property>
    <property name="dataSource" ref="shareddDataSource" />
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="database" value="MYSQL" />
            <property name="showSql" value="false" />
            <property name="generateDdl" value="false" />
        </bean>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="javax.persistence.transactionType" value="JTA" />
            <entry key="hibernate.transaction.manager_lookup_class"
                value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup" />
            <entry key="hibernate.connection.autocommit" value="false" />
        </map>
    </property>
</bean>

и транзакция.xml:

    <tx:annotation-driven proxy-target-class="true" />

<tx:jta-transaction-manager
    transaction-manager="atomikosTransactionManager" />

<tx:annotation-driven transaction-manager="atomikosTransactionManager"
    proxy-target-class="true" />

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
    init-method="init" destroy-method="close">
    <property name="forceShutdown" value="false" />
</bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
    <property name="transactionTimeout" value="300" />
</bean>

<bean id="transactionManager"
    class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="userTransaction" ref="atomikosUserTransaction" />
    <property name="allowCustomIsolationLevels" value="true" />
</bean>

* РЕДАКТИРОВАТЬ (19.01.2014) *

Таким образом, согласно помощи М. Дейна, нам удалось устранить ошибку, но теперь нет никакой действительной транзакции (исключение, например, не происходит отката).

Вот наша новая конфигурация:

данных source.xml:

    <bean id="xaDataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
    lazy-init="true">
    <property name="pinGlobalTxToPhysicalConnection" value="true" />
    <property name="url" value="${mysql_url}" />
    <property name="user" value="root" />
    <property name="password" value="6918001" />
</bean>

   <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="jtaDataSource" ref="xaDataSource" />
  <property name="packagesToScan" value="com.xxx.model" />
  <property name="jpaProperties">
      <props>
         <prop key="hibernate.hbm2ddl.auto">update</prop>
         <prop     key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup        </prop>
     </props>
   </property>
 <property name="jpaVendorAdapter">
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
         <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
         <property name="showSql" value="false" />
         <property name="generateDdl" value="false" />
     </bean>
 </property>
</bean>

 <bean id="shardXaDataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
    lazy-init="true">
    <property name="pinGlobalTxToPhysicalConnection" value="true" />
    <property name="url" value="${shared_mysql_url}" />
    <property name="user" value="root" />
    <property name="password" value="6918001" />
</bean>


 <bean id="sharedEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jtaDataSource" ref="shardXaDataSource" />
<property name="packagesToScan" value="com.xxx.shared.model" />
<property name="jpaProperties">
    <props>
        <prop key="hibernate.hbm2ddl.auto">update</prop>
        <prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
    </props>
</property>
<property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
        <property name="showSql" value="false" />
        <property name="generateDdl" value="false" />
    </bean>
</property>

transaction.xml:

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/tx
                    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

<tx:annotation-driven proxy-target-class="true" /> 


 <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
 </bean>

 <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
 </bean>

 <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
 <property name="transactionManager" ref="atomikosTransactionManager" />
 <property name="userTransaction" ref="atomikosUserTransaction" />
 <property name="allowCustomIsolationLevels" value="true" />
</bean>

</beans>

* РЕДАКТИРОВАТЬ 20/20/2014 *

Нам удалось заставить его работать, но множество предупреждений при запуске:

   20 Jan 2014 15:14:16  WARN AbstractDataSourceBean - AtomikosDataSoureBean 'xaDataSource': poolSize equals default - this may cause performance problems!
20 Jan 2014 15:14:17  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:17  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:17  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:17  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:17  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:17  WARN JtaPlatformInitiator - HHH000427: Using deprecated    org.hibernate.transaction.TransactionManagerLookup strategy [hibernate.transaction.manager_lookup_class],        use newer org.hibernate.service.jta.platform.spi.JtaPlatform strategy instead    [hibernate.transaction.jta.platform]
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AbstractDataSourceBean - AtomikosDataSoureBean 'sharedXaDataSource': poolSize equals default - this may cause performance problems!
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN JtaPlatformInitiator - HHH000427: Using deprecated org.hibernate.transaction.TransactionManagerLookup strategy [hibernate.transaction.manager_lookup_class], use newer org.hibernate.service.jta.platform.spi.JtaPlatform strategy instead [hibernate.transaction.jta.platform]
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN EntityManagerFactoryRegistry - HHH000436: Entity manager factory name (default) is already registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'
20 Jan 2014 15:14:18  WARN UserTransactionServiceImp - No properties path set - looking for transactions.properties in classpath...
20 Jan 2014 15:14:18  WARN UserTransactionServiceImp - transactions.properties not found - looking for jta.properties in classpath...
20 Jan 2014 15:14:18  WARN UserTransactionServiceImp - Failed to open transactions properties file - using default values
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator     10.0.50.117.tm0050100104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050100104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050200104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050200104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050300104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050300104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050400104 with state COMMITTING

Новая конфигурация:

<bean id="xaDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
    init-method="init" destroy-method="close">
    <property name="xaDataSourceClassName">
        <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>
    </property>
    <property name="uniqueResourceName"><value>xaDataSource</value></property>      
     <property name="xaProperties">
        <props>
            <prop key="url">${mysql_url}</prop>
            <prop key="user">root</prop>
            <prop key="password">xxx</prop>
        </props>
    </property>
</bean>

<bean id="sharedXaDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
    init-method="init" destroy-method="close">
    <property name="xaDataSourceClassName">
        <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>
    </property>
    <property name="uniqueResourceName"><value>sharedXaDataSource</value></property>
    <property name="xaProperties">
        <props>
            <prop key="url">${shared_mysql_url}</prop>
            <prop key="user">root</prop>
            <prop key="password">xxx</prop>
        </props>
    </property>
</bean>

2 ответа

Решение
<tx:annotation-driven proxy-target-class="true" />

<tx:jta-transaction-manager
    transaction-manager="atomikosTransactionManager" />

<tx:annotation-driven transaction-manager="atomikosTransactionManager"
    proxy-target-class="true" />

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
    init-method="init" destroy-method="close">
    <property name="forceShutdown" value="false" />
</bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
    <property name="transactionTimeout" value="300" />
</bean>

<bean id="transactionManager"
    class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="userTransaction" ref="atomikosUserTransaction" />
    <property name="allowCustomIsolationLevels" value="true" />
</bean>

Ваша конфигурация имеет недостатки и содержит дубликаты, что, вероятно, смущает весну. Оба JtaTransactionManager так же как <tx:jta-transaction-manager /> создать JtaTransactionManager,

Следующий твой <tx:annotation-driven > следует указать на JtaTransactionManager но это указывает на UserTransactionManager,

Итак, сначала исправьте вашу конфигурацию:

<tx:annotation-driven proxy-target-class="true" />

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
    init-method="init" destroy-method="close">
    <property name="forceShutdown" value="false" />
</bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
    <property name="transactionTimeout" value="300" />
</bean>

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="userTransaction" ref="atomikosUserTransaction" />
    <property name="allowCustomIsolationLevels" value="true" />
</bean>

Предполагая, что вы используете последнюю версию Spring 3.2 вместо введения dataSource свойство залить jtaDataSource на ваше LocalContainerEntityManagerFactoryBeanрядом ваш jpaProperties а также jpaPropertiesMap можно почистить

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jtaDataSource" ref="xaDataSource" />
    <property name="packagesToScan" value="com.xxx.model" />
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
        </props>
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
            <property name="showSql" value="false" />
            <property name="generateDdl" value="false" />
        </bean>
    </property>
</bean>

hibernate.connection свойства бесполезны, поскольку вы вводите источник данных, управляемый Spring. Из-за инъекции jtaDataSource jpaProperty для javax.persistence.transactionType могут быть удалены. HibernateJpaVendorAdapter уже устанавливает HibernateJpaDialect и вы можете использовать databasePlatform свойство указывать диалект.

Что касается ваших источников данных, вы должны использовать обертки Atomikos для источников данных, чтобы они знали об Atomikos. Для этого используйте AtomikosDataSourceBean вместо xa предоставил источник данных для вашего драйвера JDBC.

<bean id="xaDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
    <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
    <property name="uniqueResourceName" value="xaDataSource"/>      
     <property name="xaProperties">
        <props>
            <prop key="url">${mysql_url}</prop>
            <prop key="user">root</prop>
            <prop key="password">xxx</prop>
        </props>
    </property>
</bean>

Наконец вы используете BasicDataSource в качестве ссылки на hibernate, в то время как вы должны использовать включенный (и упакованный) источник данных xa.

Попробуйте это: На вашей транзакции Менеджеры добавляют:

<qualifier value="transactionManager1"/> 

пример:

<bean id="transactionManager1" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory1" />
    <qualifier value="transactionManager1"/>
</bean>

Затем в вашей реализации DAO сделать что-то вроде этого:

@Repository("Users1DAO")
public class Users1DAOJpaImp implements Users1DAO {

    @PersistenceContext(unitName="datasources1")
    @Qualifier("transactionTemplate1")
    private EntityManager em;

    @Override
    @Transactional(value="transactionManager1",  readOnly = false, propagation = Propagation.MANDATORY)
    public void save(Users1 user) {
        em.persist(user);
    }

}
Другие вопросы по тегам