分布式事務操作之Spring+JTA+ibatis
一、技術背景
在項目中需要操作多個數據庫,同時,需要保證操作的原子性,保證對多個數據庫的操作一致性,而傳統的JDBC事務被限定在一個單一的數據庫連接中,故引用JTA,即Java Transaction API。JTA事務比JDBC事務更強大,一個JTA事務可以有多個數據源參與者。
現在,我們用spring+jta+ibatis來完成基本的測試框架。
二、技術實現
第一步:導入JOTM Jar包
JOTM (Java Open Transaction Manager),一個開源JTA實現,是由ObjectWeb協會開發的功能完整的獨立的事務管理器。下載JOTM(ow2-jotm-dist-2.2.1-bin.tar.gz),解壓tar包導入lib目錄下的Jar包。或在Maven pom.xml中添加:
org.ow2.jotm
ow2-jotm-dist
2.2.1
pom
compile
第二步:創建JotmFactoryBean
spring為JOTM提供了一個org.springframework.transaction.jta.JotmFactoryBean支持類,通過該支持類可以方便地創建JOTM本地實例。但是spring3以後spring-tx.jar 沒有JotmFactoryBean的支持,可以反編譯spring2.5的spring-tx.jar,copy新建一個類。
import javax.naming.NamingException;
import javax.transaction.SystemException;
import org.objectweb.jotm.Current;
import org.objectweb.jotm.Jotm;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
public class JotmFactoryBean implements FactoryBean, DisposableBean {
private Current jotmCurrent;
private Jotm jotm;
public JotmFactoryBean() throws NamingException {
jotmCurrent = Current.getCurrent();
if (jotmCurrent == null) {
jotm = new Jotm(true, false);
jotmCurrent = Current.getCurrent();
}
}
public void setDefaultTimeout(int defaultTimeout) {
jotmCurrent.setDefaultTimeout(defaultTimeout);
try {
jotmCurrent.setTransactionTimeout(defaultTimeout);
} catch (SystemException ex) {
}
}
public Jotm getJotm() {
return jotm;
}
public Object getObject() {
return jotmCurrent;
}
public Class getObjectType() {
return jotmCurrent.getClass();
}
public boolean isSingleton() {
return true;
}
public void destroy() {
if (jotm != null)
jotm.stop();
}
}
第三步:創建DAO
創建基於ibatis框架的DAO接口和實現類。
IBaseDao
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
/**
* Title:
* Description: Dao 接口類
*/
public interface IBaseDao {
/**
* 根據Id獲取對象
*
* @param id 主鍵
* @param sqlId 腳本編號
* @return Object對象
*/
public Object queryForObject(int id, String sqlId);
/**
* 根據Id獲取對象
*
* @param id 主鍵
* @param cls 返回的對象Class
* @param sqlId 腳本編號
* @return cls對應的類
*/
public T queryForObject(int id, Class cls, String sqlId);
/**
* 根據條件獲取對象
*
* @param params 參數
* @param sqlId 腳本編號
* @return Object對象
*/
public Object queryForObject(Map params, String sqlId);
/**
* 根據條件獲取對象
*
* @param params 參數
* @param cls 返回的對象Class
* @param sqlId 腳本編號
* @return cls對應的類
*/
public T queryForObject(Map params, Class cls, String sqlId);
/**
* 獲取數據總條數
*
* @param params 參數
* @param sqlId 腳本編號
* @return 條數
*/
public int getTotalCount(Map params, String sqlId);
/**
* 查詢列表
*
* @param params 參數
* @param cls 返回的對象Class
* @param sqlId 腳本編號
* @return 列表
*/
public List queryForList(Map params, Class cls, String sqlId);
/**
* 查詢列表
*
* @param params 參數
* @param sqlId 腳本編號
* @return 列表
*/
public List