Spring分布式事務實現

jopen 11年前發布 | 90K 次閱讀 Spring JEE框架

       分布式事務是指操作多個數據庫之間的事務,spring的org.springframework.transaction.jta.JtaTransactionManager,提供了分布式事務支持。如果使用WAS的JTA支持,把它的屬性改為WebSphere對應的TransactionManager。 
       在tomcat下,是沒有分布式事務的,不過可以借助于第三方軟件jotm(Java Open Transaction Manager )和AtomikosTransactionsEssentials實現,在spring中分布式事務是通過jta(jotm,atomikos)來進行實現。 
1、http://jotm.objectweb.org/ 
2、http://www.atomikos.com/Main/TransactionsEssentials 

一、使用JOTM例子 
(1) Dao及實現 

GenericDao接口:

public interface GenericDao {
    public int save(String ds, String sql, Object[] obj) throws Exception;  
    public int findRowCount(String ds, String sql); 
}

GenericDaoImpl 實現:

public class GenericDaoImpl implements GenericDao{

private  JdbcTemplate jdbcTemplateA;
private  JdbcTemplate jdbcTemplateB;

public void setJdbcTemplateA(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplateA = jdbcTemplate;
}

public void setJdbcTemplateB(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplateB = jdbcTemplate;
}

public int save(String ds, String sql, Object[] obj) throws Exception{
    if(null == ds || "".equals(ds)) return -1;
    try{
        if(ds.equals("A")){
            return this.jdbcTemplateA.update(sql, obj);
        }else{
            return this.jdbcTemplateB.update(sql, obj);
        }
    }catch(Exception e){
        e.printStackTrace();
        throw new Exception("執行" + ds + "數據庫時失敗!");
    }
}

public int findRowCount(String ds, String sql) {
    if(null == ds || "".equals(ds)) return -1;

    if(ds.equals("A")){
        return this.jdbcTemplateA.queryForInt(sql);
    }else{
        return this.jdbcTemplateB.queryForInt(sql);
    }
}

}</pre>

(2) Service及實現 

UserService 接口:

public interface UserService {
    public void saveUser() throws Exception;
}

UserServiceImpl 實現:

public class UserServiceImpl implements UserService{

private GenericDao genericDao;

public void setGenericDao(GenericDao genericDao) {
    this.genericDao = genericDao;
}

public void saveUser() throws Exception {
    String userName = "user_" + Math.round(Math.random()*10000);
    System.out.println(userName);

    StringBuilder sql = new StringBuilder();
    sql.append(" insert into t_user(username, gender) values(?,?); ");
    Object[] objs = new Object[]{userName,"1"};

    genericDao.save("A", sql.toString(), objs);

    sql.delete(0, sql.length());
    sql.append(" insert into t_user(name, sex) values(?,?); ");
    objs = new Object[]{userName,"男的"};//值超出范圍
    genericDao.save("B", sql.toString(), objs);
}

}</pre>

 

(3) applicationContext-jotm.xml 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="

</beans></pre>


(4) 測試 

public class TestUserService{

private static UserService userService;

@BeforeClass
public static void init(){
    ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext-jotm.xml");
    userService = (UserService)app.getBean("userService");
}

@Test
public void save(){
    System.out.println("begin...");
    try{
        userService.saveUser();
    }catch(Exception e){
        System.out.println(e.getMessage());
    }
    System.out.println("finish...");
}

}</pre>

二、關于使用atomikos實現 
(1) 數據源配置 

<bean id="dataSourceA" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close">
    <property name="uniqueResourceName">
        <value>${datasource.uniqueResourceName}</value>
    </property>
    <property name="xaDataSourceClassName"> 
        <value>${database.driver_class}</value> 
    </property> 
    <property name="xaDataSourceProperties">
        <value>URL=${database.url};user=${database.username};password=${database.password}</value> 
    </property> 
    <property name="exclusiveConnectionMode"> 
        <value>${connection.exclusive.mode}</value> 
    </property>
    <property name="connectionPoolSize"> 
        <value>${connection.pool.size}</value>
    </property>
    <property name="connectionTimeout">
        <value>${connection.timeout}</value>
    </property>
    <property name="validatingQuery"> 
        <value>SELECT 1</value> 
    </property> 
</bean>

(2)、事務配置 
  <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" 
        init-method="init" destroy-method="close"> 
        <property name="forceShutdown" value="true"/> 
    </bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> 
    <property name="transactionTimeout" value="${transaction.timeout}"/> 
</bean>

<!-- JTA事務管理器 --> 
<bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> 
    <property name="transactionManager" ref="atomikosTransactionManager"/> 
    <property name="userTransaction" ref="atomikosUserTransaction"/> 
</bean>

<!-- 事務切面配置 --> 
<aop:config> 
    <aop:pointcut id="serviceOperation"  expression="execution(* *..service*..*(..))"/> 
    <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/> 
</aop:config>

<!-- 通知配置 -->
<tx:advice id="txAdvice" transaction-manager="springTransactionManager"> 
    <tx:attributes>
        <tx:method name="*" rollback-for="Exception"/> 
    </tx:attributes> 
</tx:advice> </pre><br />


有關JTA
JTA全稱為Java Transaction API,顧名思義JTA定義了一組統一的事務編程的接口,這些接口如下:
 
XAResource 
XAResource接口是對實現了X/Open CAE規范的資源管理器 (Resource Manager,數據庫就是典型的資源管理器) 的抽象,它由資源適配器 (Resource Apdater) 提供實現。XAResource是支持事務控制的核心。

Transaction
Transaction接口是一個事務實例的抽象,通過它可以控制事務內多個資源的提交或者回滾。二階段提交過程也是由Transaction接口的實現者來完成的。

TransactionManager
托管模式 (managed mode) 下,TransactionManager接口是被應用服務器調用,以控制事務的邊界的。
 
UserTransaction
非托管模式 (non-managed mode) 下,應用程序可以通過UserTransaction接口控制事務的邊界
 
托管模式下的事務提交場景

20130901231943312.jpg

注意:在上圖中3和5的步驟之間省略了應用程序對資源的操作 (如CRUD)。另外,應用服務器什么時機 enlistResource,又是什么時候delistResource呢?這在后文中會解釋。

 

有關JCA

下圖為JCA的架構圖

20130901231957500.jpg

中間涉及元素說明如下:
1)Enterprise Information System
簡稱EIS,在JTA中它又被稱為資源管理器。典型的EIS有數據庫,事務處理系統(Transaction Processing System),ERP系統。
 
2)Resource Adapter
資源適配器(Resource Adaper)是JCA的關鍵。要想把不同的EIS整合(或者連接)到J2EE運行環境中,就必須為每個EIS提供資源適配器,它會將將EIS適配為一個具備統一編程接口的資源 (Resource) 。這個統一編程接口就是上圖中的System Contracts和Client API。下面的UML類圖將完美詮釋資源適配器。

 

3)Application Server
應用服務器 (Application Server) 通過System Contracts來管理對EIS的安全、事務、連接等。典型的應用服務器有JBoss、JOnAS、Geronimo、GlassFish等。
 
4)Application Component 
應用組件 (Application Component) ,它封裝了應用業務邏輯,像對資源的訪問和修改。典型的應用組件就是EJB。
 
更多細節請參見:
Sun Microsystems Inc.J2EE Connector Architecture 1.5 

 

來自:
http://blog.csdn.net/ithomer/article/details/10859235

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!