Complete example of the Code involved in this article download http://download.csdn.net/download/lanseba/2508881
Sometimes our program has more than one data source and needs to ensure transactions in multiple data sources, so we need to use distributed transactions... JTA -- Java transaction API .. Brother studied it. I made a summary and shared it with you. In order to solve the problem of distributed transactions once and for all.
Environment: mysql5.1 JDK 1.5 + spring 2.5 hibernate 3.x spring supports JTA very well...
Distributed transactions must support databases and provide XA connection drivers. For example, MySQL 5.0 and later versions have com. mySQL. JDBC. jdbc2.optional. mysqlxaconnection and other connections that support XA distributed transactions, so we naturally need to use this XA connection to use XA transactions.
Of course, the above mentioned mysql5.1 is to support distributed transactions, MySQL driver needs 5.0 + brother recommended mysql-connector-java-5.1.0
After comparison, I think this driver is the most stable and has the best support for Xa.
Configure the code on the second!
Database 1: jtatest1
Table: tusers
Column Type
Id int primary key auto-Increment
Name varchar (50) not empty
--------------------------------------------------------
Create Table 'tusers '(
'Id' int (11) not null auto_increment,
'Name' varchar (50) not null,
Primary Key ('id ')
) Engine = InnoDB auto_increment = 3 default charset = utf8;
Database 1: jtatest2
Table: Product
Column Type
Id int primary key auto-Increment
Price float (11,0) is not empty
--------------------------------------------------------
Create Table 'product '(
'Id' int (11) not null auto_increment,
'Price' float (11,0) not null,
Primary Key ('id ')
) Engine = InnoDB auto_increment = 18 default charset = utf8;
Object Class and hibernate ORM ing File
Package jtatest1;
Public class users implements java. Io. serializable {
Private integer ID;
Private string name;
Public users (){
}
Public users (integer ID, string name ){
This. ID = ID;
This. Name = Name;
}
Public integer GETID (){
Return this. ID;
}
Public void setid (integer ID ){
This. ID = ID;
}
Public String getname (){
Return this. Name;
}
Public void setname (string name ){
This. Name = Name;
}
}
<? XML version = "1.0" encoding = "UTF-8"?>
<! Doctype hibernate-mapping public "-// hibernate/hibernate mapping DTD 3.0 // en"
Http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd>
<Hibernate-mapping>
<Class name = "jtatest1.users" table = "tusers">
<ID name = "ID" type = "Java. Lang. Integer">
<Column name = "ID"/>
<Generator class = "Identity"/>
</ID>
<Property name = "name" type = "Java. Lang. String">
<Column name = "name" length = "100" not-null = "true"/>
</Property>
</Class>
</Hibernate-mapping>
Package jtatest2;
Public class product implements java. Io. serializable {
Private integer ID;
Private float price;
Public Product (){
}
Public Product (integer ID, float price ){
This. ID = ID;
This. Price = price;
}
Public integer GETID (){
Return this. ID;
}
Public void setid (integer ID ){
This. ID = ID;
}
Public float getprice (){
Return this. price;
}
Public void setprice (float price ){
This. Price = price;
}
}
<? XML version = "1.0" encoding = "UTF-8"?>
<! Doctype hibernate-mapping public "-// hibernate/hibernate mapping DTD 3.0 // en"
Http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd>
<Hibernate-mapping>
<Class name = "jtatest2.product" table = "product">
<ID name = "ID" type = "Java. Lang. Integer">
<Column name = "ID"/>
<Generator class = "Identity"/>
</ID>
<Property name = "price" type = "Java. Lang. Float">
<Column name = "price" precision = "53" scale = "0" not-null = "true"/>
</Property>
</Class>
</Hibernate-mapping>
Below are Dao and biz
Package jtatest. daoimpl;
Import jtatest. Dao. productdao;
Import jtatest2.product;
Import org. springframework. Orm. hibernate3.support. hibernatedaosupport;
Public class productdaoimpl extends hibernatedaosupport implements productdao {
Public void save (product P ){
This. gethibernatetemplate (). Save (P );
}
}
Package jtatest. daoimpl;
Import jtatest. Dao. userdao;
Import jtatest1.users;
Import org. springframework. Orm. hibernate3.support. hibernatedaosupport;
Public class userdaoimpl extends hibernatedaosupport implements userdao {
Public void save (users U ){
This. gethibernatetemplate (). Save (U );
}
}
Package jtatest. Dao;
Import jtatest2.product;
Public interface productdao {
Public abstract void save (product P );
}
Package jtatest. Dao;
Import jtatest1.users;
Public interface userdao {
Public abstract void save (users U );
}
Package jtatest. bizimpl;
Import jtatest. biz. Biz;
Import jtatest. Dao. productdao;
Import jtatest. Dao. userdao;
Import jtatest1.users;
Import jtatest2.product;
Public class bizimpl implements biz {
Private productdao = NULL;
Private userdao = NULL;
Public void save (product P, users U ){
Productdao. Save (P );
Userdao. Save (U );
}
Public void setproductdao (productdao ){
This. productdao = productdao;
}
Public void setuserdao (userdao ){
This. userdao = userdao;
}
}
Package jtatest. Biz;
Import jtatest1.users;
Import jtatest2.product;
Public interface biz {
Public void save (product P, users U );
}
2 hibernate configurations
Hibernate-jtatest1.cfg.xml
<Hibernate-configuration>
<Session-factory>
<Property name = "dialect"> org. hibernate. dialect. mysqldialect </property>
<Property name = "show_ SQL"> true </property>
<Mapping Resource = "jtatest1/users. HBM. xml"/>
</Session-factory>
</Hibernate-configuration>
-------------------------------------------
Hibernate-jtatest2.cfg.xml
<Hibernate-configuration>
<Session-factory>
<Property name = "dialect"> org. hibernate. dialect. mysqldialect </property>
<Property name = "show_ SQL"> true </property>
<Mapping Resource = "jtatest2/product. HBM. xml"/>
</Session-factory>
</Hibernate-configuration>
Well, the basic spam code is the above. The rest is to use spring to manage JTA. You can use jotm or atomikos, but it seems that jotm needs the support of JNDI, but it cannot be removed from the web server,
While atomikos does not need the support of JNDI so brother recommended to use atomikos it is also an open source product, http://www.atomikos.com/downloads/transactions-essentials/3.5.5/AtomikosTransactionsEssentials-3.5.5.zip
You don't need to write a transaction code to manage JTA transactions using spring. It's really Nb...
You may not have a username or password in the hibernate configuration. This is because we need to inject a xadatasource to hibernate in spring so that the connection obtained by Hibernate is xaconnection.
Here we use the xadatasource configuration of atomikos:
<Bean id = "ds1" class = "com. atomikos. JDBC. simpledatasourcebean"
Init-method = "init" Destroy-method = "close">
<Property name = "uniqueresourcename">
<Value> MySQL/ds1 </value> note that multiple datasource names cannot be duplicated.
</Property>
<Property name = "xadatasourceclassname">
<Value> com. MySQL. JDBC. jdbc2.optional. mysqlxadatasource </value>
</Property>
<Property name = "xadatasourceproperties">
<Value> url = JDBC: mysql: // localhost: 3306/jtatest1? User = root; Password = admin </value>
</Property>
<Property name = "exclusiveconnectionmode">
<Value> true </value>
</Property>
<Property name = "connectionpoolsize">
<Value> 3 </value>
</Property>
<Property name = "validatingquery">
<Value> select 1 </value>
</Property>
</Bean>
<Bean id = "DS2"
Class = "com. atomikos. JDBC. simpledatasourcebean" init-method = "init"
Destroy-method = "close">
<Property name = "uniqueresourcename">
<Value> MySQL/DS2 </value>
</Property>
<Property name = "xadatasourceclassname">
<Value> com. MySQL. JDBC. jdbc2.optional. mysqlxadatasource </value>
</Property>
<Property name = "xadatasourceproperties">
<Value> url = JDBC: mysql: // localhost: 3306/jtatest2? User = root; Password = admin </value>
</Property>
<Property name = "exclusiveconnectionmode">
<Value> true </value>
</Property>
<Property name = "connectionpoolsize">
<Value> 3 </value>
</Property>
<Property name = "validatingquery">
<Value> select 1 </value>
</Property>
</Bean>
In this way, we can inject datasource to hibernate.
<Bean id = "sessionfactory1"
Class = "org. springframework. Orm. hibernate3.localsessionfactorybean">
<Property name = "configlocation"
Value = "classpath: hibernate-jtatest1.cfg.xml"/>
<Property name = "datasource" ref = "ds1"> </property>
</Bean>
<Bean id = "sessionfactory2"
Class = "org. springframework. Orm. hibernate3.localsessionfactorybean">
<Property name = "configlocation"
Value = "classpath: hibernate-jtatest2.cfg.xml"/>
<Property name = "datasource" ref = "DS2"> </property>
</Bean>
Manage biz and Dao below
<Bean id = "biz" class = "jtatest. bizimpl. bizimpl">
<Property name = "productdao" ref = "productdao"/>
<Property name = "userdao" ref = "userdao"/>
</Bean>
<Bean id = "userdao" class = "jtatest. daoimpl. userdaoimpl">
<Property name = "sessionfactory" ref = "sessionfactory1"/>
</Bean>
<Bean id = "productdao" class = "jtatest. daoimpl. productdaoimpl">
<Property name = "sessionfactory" ref = "sessionfactory2"/>
</Bean>
OK, everything is ready, and the transaction is almost the same as the general transaction process managed by spring.
First, a Transaction Manager is required.
<Bean id = "atomikostransactionmanager"
Class = "com. atomikos. icatch. JTA. usertransactionmanager"
Init-method = "init" Destroy-method = "close">
<Property name = "forceshudown">
<Value> true </value>
</Property>
</Bean>
Com. atomikos. icatch. JTA. usertransactionmanager implements the javax. transaction. transactionmanager interface. This interface cannot be compatible with the transaction-manager of TX: advice.
, So needs to be packaged
<Bean id = "txmanager"
Class = "org. springframework. transaction. JTA. jtatransactionmanager">
<Property name = "usertransaction" ref = "atomikosusertransaction"/>
<Property name = "transactionmanager" ref = "atomikostransactionmanager"> </property>
</Bean>
This is the implementation of atomikos transactions.
<Bean id = "atomikosusertransaction"
Class = "com. atomikos. icatch. JTA. usertransactionimp">
<Property name = "transactiontimeout">
<Value> 6000 </value>
</Property>
</Bean>
In this way, the txmanager is put on the spring Transaction Manager coat.
The following figure shows the woven notification.
<TX: Advice id = "advice" transaction-Manager = "txmanager">
<TX: Attributes>
<TX: method name = "Save *" propagation = "required"/>
<TX: method name = "delete *" propagation = "required"/>
<TX: method name = "*" Read-Only = "false"/>
</TX: Attributes>
</TX: Advice>
<AOP: config>
<AOP: pointcut id = "point"
Expression = "execution (* jtatest. bizimpl. *. * (...)"/>
<AOP: Advisor advice-ref = "advice" pointcut-ref = "point"/>
</AOP: config>
You can test it.
Public static void main (string [] ARGs ){
Applicationcontext context = new classpathxmlapplicationcontext (New String [] {"applicationcontext. xml "});
Beanfactory BF = context;
Biz biz = (BIZ) BF. getbean ("biz ");
Product P = new product ();
P. setprice (10f );
Users u = new users ();
U. setname (null); // insert an empty field and try again.
Biz. Save (p, U );
}