У меня есть простое веб-приложение, использующее JTA + JPA вместе с Spring (версия 4). Я делаю транзакцию XA с помощью диспетчера транзакций Atomikos JTA. Эта транзакция включает в себя включение объекта EmployeeA в DatabaseA и другой объект EmployeeB в другой DatabaseB.Как вставить в базу данных при использовании JTA + JPA с пружиной
Странно, приложение не вызывает никаких ошибок , но никакие энтеи не вставляются в Базы данных.
public class JtaTest {
public static void main(String[] args) {
JtaTest test = new JtaTest();
test.testMandatory();
}
private static void testMandatory() {
final SpringContextUtil util = SpringContextUtil.instance();
ApplicationContext ctx = util.getApplicationContext();
final JtaEmployeeService employeeService = (JtaEmployeeService)ctx.getBean("jtaEmployeeService");
EmployeeA a = new EmployeeA();
a.setName("emp-a-1");
a.setAge(30);
EmployeeB b = new EmployeeB();
a.setName("emp-b-1");
a.setAge(31);
try {
employeeService.persistEmployees(a, b);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("success");
}
}
Реализация класса обслуживания:
@Service("jtaEmployeeService")
public class JtaEmployeeServiceImpl implements JtaEmployeeService {
@Autowired
@Qualifier("employeea")
private GenericDao<Integer, EmployeeA> employeeADao;
@Autowired
@Qualifier("employeeb")
private GenericDao<Integer, EmployeeB> employeeBDao;
@Override
@Transactional(propagation=Propagation.REQUIRED, readOnly=false, isolation=Isolation.DEFAULT, rollbackFor=Exception.class)
public void persistEmployees(EmployeeA employeeA, EmployeeB employeeB) throws Exception {
employeeADao.save(employeeA);
employeeBDao.save(employeeB);
System.out.println("Saving employee A and employee B ");
}
}
Реализация DAO и интерфейсы:
@Repository("employeeb")
public class EmployeeBDaoImpl extends AbstractJTADaoDatabaseB implements
GenericDao<Integer, EmployeeB> {
@Override
public void save(EmployeeB entity) {
super.persist(entity);
}
}
@Repository("employeea")
public class EmployeeADaoImpl extends AbstractJTADaoDatabaseA implements
GenericDao<Integer, EmployeeA> {
@Override
public void save(EmployeeA entity) {
super.persist(entity);
}
}
public abstract class AbstractJTADaoDatabaseB {
@PersistenceContext(unitName = "persistenceUnitB")
@Qualifier("myManager")
private EntityManager entityManager;
public void persist(Object entity) {
entityManager.persist(entity);
// entityManager.flush();
}
protected EntityManager getEntityManager() {
return entityManager;
}
}
public abstract class AbstractJTADaoDatabaseA {
@PersistenceContext(unitName = "persistenceUnitA")
@Qualifier("myManager")
private EntityManager entityManager;
public void persist(Object entity) {
entityManager.persist(entity);
// entityManager.flush();
}
protected EntityManager getEntityManager() {
return entityManager;
}
}
сервлетов-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
\t xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
\t xmlns:beans="http://www.springframework.org/schema/beans"
\t xmlns:context="http://www.springframework.org/schema/context"
\t xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
\t xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
\t \t http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
\t \t http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
\t \t http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
\t <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
\t
\t <!-- Enables the Spring MVC @Controller programming model -->
\t <annotation-driven />
\t
\t <!-- Enables annotaion driven transactional support on springs -->
\t <!-- <tx:annotation-driven transaction-manager="hTransactionManager"/> -->
\t <!-- <tx:jta-transaction-manager transaction-manager="jtaTransactionManager"/> -->
\t <tx:annotation-driven transaction-manager="jtaTransactionManager"/>
<!-- list the packages which are annotated with springs annotaions like @controller, @repository, @service, @component only -->
\t <context:component-scan base-package="com.goraksh.spring.tutorial.controller.business, com.goraksh.spring.tutorial.controller.rest, com.goraksh.spring.tutorial.service, com.goraksh.spring.tutorial.dao" />
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
\t <beans:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<beans:property name="location" value="classpath:application.properties"/>
</beans:bean>
<!-- <beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.annotation.AnnotationSessionFactoryBean"> -->
<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</beans:prop>
<!-- <beans:prop key="hibernate.current_session_context_class">thread</beans:prop> -->
<beans:prop key="hibernate.show_sql">${hibernate.show_sql}</beans:prop>
<beans:prop key="hibernate.format_sql">${hibernate.format_sql}</beans:prop>
<beans:prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</beans:prop>
<beans:prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</beans:prop>
<beans:prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</beans:prop>
<beans:prop key="net.sf.ehcache.configurationResourceName">${net.sf.ehcache.configurationResourceName}</beans:prop>
</beans:props>
</beans:property>
<!--<beans:property name="annotatedClasses"> -->
<!-- packagesToScan is meant to give the package where the javax.persistence.Entity classes are stored , recognised via their annotations-->
<beans:property name="packagesToScan">
<beans:list>
<beans:value>com.goraksh.spring.tutorial.model</beans:value>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<beans:property name="driverClassName" value="${jdbc.driverClassName}"/>
<beans:property name="url" value="${jdbc.url}"/>
<beans:property name="username" value="${jdbc.username}"/>
<beans:property name="password" value="${jdbc.password}"/>
</beans:bean>
<beans:bean id = "hTransactionManager" class = "org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name = "sessionFactory" ref = "sessionFactory" />
</beans:bean>
\t
<!-- Jata transactions with Atomikos -->
<beans:bean id="dataSourceA" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
\t <beans:property name="uniqueResourceName"><beans:value>DataSourceA</beans:value></beans:property>
\t <beans:property name="xaDataSourceClassName"><beans:value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</beans:value></beans:property>
\t <beans:property name="xaProperties">
\t <beans:props>
\t \t <beans:prop key="databaseName">traningdb</beans:prop>
\t \t <beans:prop key="serverName">localhost</beans:prop>
\t \t <beans:prop key="port">3306</beans:prop>
\t \t <beans:prop key="user">root</beans:prop>
\t \t <beans:prop key="password">root</beans:prop>
\t \t <beans:prop key="url">jdbc:mysql://localhost:3306/traningdb</beans:prop>
\t </beans:props>
\t </beans:property>
\t <beans:property name="minPoolSize"><beans:value>1</beans:value></beans:property>
</beans:bean>
\t
<beans:bean id="dataSourceB" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
\t <beans:property name="uniqueResourceName"><beans:value>DataSourceB</beans:value></beans:property>
\t <beans:property name="xaDataSourceClassName"><beans:value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</beans:value></beans:property>
\t <beans:property name="xaProperties">
\t <beans:props>
\t \t <beans:prop key="databaseName">traningdb2</beans:prop>
\t \t <beans:prop key="serverName">localhost</beans:prop>
\t \t <beans:prop key="port">3306</beans:prop>
\t \t <beans:prop key="user">root</beans:prop>
\t \t <beans:prop key="password">root</beans:prop>
\t \t <beans:prop key="url">jdbc:mysql://localhost:3306/traningdb2</beans:prop>
\t </beans:props>
\t </beans:property>
\t <beans:property name="minPoolSize">
\t <beans:value>1</beans:value>
\t </beans:property>
</beans:bean>
<beans:bean id="entityManagerFactoryA" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
\t <beans:property name="persistenceXmlLocation">
<beans:value>classpath:META-INF/persistence.xml</beans:value>
</beans:property>
\t \t <beans:property name="persistenceUnitName" value="persistenceUnitA" />
\t \t <beans:property name="dataSource" ref="dataSourceA" />
\t \t <beans:property name="jpaVendorAdapter">
\t \t \t <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
\t \t \t \t <beans:property name="showSql" value="true" />
\t \t \t \t <beans:property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
\t \t \t </beans:bean>
\t \t </beans:property>
\t </beans:bean>
\t
\t <beans:bean id="entityManagerFactoryB" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
\t <beans:property name="persistenceXmlLocation">
<beans:value>classpath:META-INF/persistence.xml</beans:value>
</beans:property>
\t \t <beans:property name="persistenceUnitName" value="persistenceUnitB" />
\t \t <beans:property name="dataSource" ref="dataSourceB" />
\t \t <beans:property name="jpaVendorAdapter">
\t \t \t <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
\t \t \t \t <beans:property name="showSql" value="true" />
\t \t \t \t <beans:property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
\t \t \t </beans:bean>
\t \t </beans:property>
\t </beans:bean>
\t <beans:bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
\t \t <beans:property name="forceShutdown" value="false" />
\t \t <!-- <beans:property name="startupTransactionService" value="false" /> -->
\t </beans:bean>
\t <beans:bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
\t \t <beans:property name="transactionTimeout" value="300" />
\t </beans:bean>
\t <beans:bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"
\t \t depends-on="atomikosTransactionManager,atomikosUserTransaction">
\t \t <beans:qualifier value="myManager"/>
\t \t <beans:property name="transactionManager" ref="atomikosTransactionManager" />
\t \t <beans:property name="userTransaction" ref="atomikosUserTransaction" />
\t \t <beans:property name="allowCustomIsolationLevels" value="true" />
\t </beans:bean>
\t
</beans:beans>
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<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="persistenceUnitA" >
<class>com.goraksh.spring.tutorial.model.EmployeeA</class>
<exclude-unlisted-classes />
<properties>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />
</properties>
</persistence-unit>
<persistence-unit name="persistenceUnitB" >
<class>com.goraksh.spring.tutorial.model.EmployeeB</class>
<exclude-unlisted-classes />
<properties>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />
</properties>
</persistence-unit>
</persistence>
Любая помощь очень нужна.