Spring + JPA + atomikos实现Oracle + SQL Server

persistence.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">

<persistence-unit name="orcaleXA" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.connection.driver_class"
value="oracle.jdbc.xa.client.OracleXADataSource" />
<property name="hibernate.connection.url"
value="jdbc:oracle:thin:name/password@192.168.201.215:1521:XE" />
<property name="hibernate.show_sql" value="true" />
<!-- property name="hibernate.transaction.factory_class"
value="com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory" /-->
<property name="hibernate.transaction.manager_lookup_class"
value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup" />
</properties>
</persistence-unit>


<persistence-unit name="sqlServerXA" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.SQLServerDialect" />
<property name="hibernate.transaction.manager_lookup_class"
value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>

atomikos文档上说不用设置hibernate.transaction.factory_class,另外发现在WAS配置Hibernate JPA也应该不要设置hibernate.transaction.factory_class。

applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<context:component-scan base-package="xx.yy.mypackage" />
<context:annotation-config />

<bean id="dataSource"
class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName">
<value>XADBMS</value>
</property>
<property name="xaDataSourceClassName">
<value>com.microsoft.sqlserver.jdbc.SQLServerXADataSource</value>
</property>
<property name="xaProperties">
<props>
<prop key="user">sa</prop>
<prop key="password">Passw0rd</prop>
<prop key="serverName">192.168.201.214</prop>
<prop key="databaseName">myDataBase</prop>
</props>
</property>
<property name="poolSize">
<value>1</value>
</property>
</bean>

<bean id="orcaleXAEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation"
value="/META-INF/persistence.xml" />
<property name="persistenceUnitName" value="orcaleXA" />
</bean>

<bean id="sqlServerXAEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation"
value="/META-INF/persistence.xml" />
<property name="persistenceUnitName" value="sqlServerXA" />
<property name="dataSource" ref="dataSource" />
</bean>

<!-- bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean-->

<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" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="find" read-only="true" />
<tx:method name="check" read-only="true" />
<tx:method name="*" read-only="false" />
</tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut id="txPointcut"
expression="execution(public * xx.yy.mypacke..*Service.*(..))" />
<aop:advisor advice-ref="txAdvice"
pointcut-ref="txPointcut" />
</aop:config>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Service
public class XxService {
@PersistenceContext(unitName = "orcaleXA")
private EntityManager oracleXaEm;

@PersistenceContext(unitName = "sqlServerXA")
private EntityManager sqlServerXaEm;
public void run(){
oracleXaEm.createQuery("...");
sqlServerXaEm.createQuery("...");
}
}

@ContextConfiguration(locations = "/applicationContext.xml")
public class TestXA extends AbstractJUnit38SpringContextTests {
@Autowired
private XxService xxService;

public void testRun() {
System.out.println("<<");
myService.go();
}
}

lib:

1
2
3
4
5
6
atomikos-util.jar 
transactions-jta.jar
transactions-api.jar
transactions.jar
transactions-hibernate3.jar
transactions-jdbc.jar