SpringMVC之WebLogicJtaTransactionManager实现全局事务管理

背景描述:随着应用系统复杂度越来越复杂,之前在一个库中完成所有业务操作已不满足现状业务系统的要求,数据流转往往存在于多个库中进行,全局事务是指在一个事务中涉及到几个事务参入者,这些事务参入者可以是我们常见的数据库操作,消息(MQ)操作等等.如同时进行下面的操作,比如"转账"操作发生在两个数据库:
1,从数据库A的的表中将某个帐号的余额减少.
2从数据库B的的表中将某个帐号的余额增加.
3,提交在数据库A中的操作.
4,提交在数据库B中的操作.
通常单个数据库只能保证本数据库的事务要么提交要么回滚,当涉及的事务跨数据库的时候,就需要一个在两个数据库之间进行事务"协调"的事务管理器了,而数据库也需要为参入这种"协调"处理实现特殊协议,叫做XA或者两阶段提交协议.Java对这种全局事务管理是通过JTA规范来做的,通常就是begin,commit或者rollback的形式,本文通过示例简单介绍一下Spring利用Weblogic提供的JTA事务管理器管理全局事务.

*注意,如果用Spring的事务声明,WebLogicJtaTransactionManager只能管理在Weblogic通过DataSource配置的数据库操作,或者在Weblogic上配置的JMS

具体操作:

第一步:在Weblogic上配置连接到两个不同数据库的DataSource,需要DataSource支持XA.

第二步:在spring-context中配置如下:

<?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:context="http://www.springframework.org/schema/context"
	xmlns:jms="http://www.springframework.org/schema/jms"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/jee
     http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">
	
    <bean id="db1jdbcDAO" class="com.test.spring.tx.xawl.dao.DB1jdbcDAO">
        <property name="dataSource" ref="dataSource1" />
    </bean>
    <bean id="db2jdbcDAO" class="com.test.spring.tx.xawl.dao.DB2jdbcDAO">
        <property name="dataSource" ref="dataSource2" />
    </bean>
    
	<bean id="dataSource1"  
        class="org.springframework.jndi.JndiObjectFactoryBean">  
        <property name="jndiName">  
            <value>DataSource-0</value>  
        </property>  
    </bean>
    <bean id="dataSource2"  
        class="org.springframework.jndi.JndiObjectFactoryBean">  
        <property name="jndiName">  
            <value>DataSource-1</value>  
        </property>  
    </bean>    
    
    <bean id="buzSingleService" class="com.test.spring.tx.xawl.Service.BuzSingleService">
        <property name="db1" ref="db1jdbcDAO" />
        <property name="db2" ref="db2jdbcDAO" />
    </bean> 
    
    <bean id="transactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager" >
        <property name="transactionManagerName" value="javax.transaction.TransactionManager" />       
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
   
    
    <!-- <context:component-scan base-package="com.test.spring.tx.xawl.controller" /> -->
   
     <context:component-scan base-package="com.test">
		<context:exclude-filter type="annotation"
			expression="org.springframework.stereotype.Service" />
	</context:component-scan>
</beans>

3,Java Dao代码:

package com.test.spring.tx.xawl.dao;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;

import com.test.spring.tx.xawl.Service.BuzSingleService;

public class DB1jdbcDAO {
	
	 private JdbcTemplate jdbcTemplate;    
	 public void setDataSource(DataSource dataSource) {
	        this.jdbcTemplate = new JdbcTemplate(dataSource);
	 }
	 public void testInsert(int id, String val) {        
		   
	        this.jdbcTemplate.update("insert into TEST1 (ID, NAME) values (?, ?)", id, val);
	 }

}
package com.test.spring.tx.xawl.dao;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;

//import weblogic.jdbc.jta.DataSource;

public class DB2jdbcDAO {  
	
	 private JdbcTemplate jdbcTemplate;    
	 public void setDataSource(DataSource dataSource) {
	        this.jdbcTemplate = new JdbcTemplate(dataSource);
	 }
	 public void testInsert(int id, String val) {   
		 
	        this.jdbcTemplate.update("insert into TEST (ID, NAME) values (?, ?)", id, val);
	 }

}

4,service代码

package com.test.spring.tx.xawl.Service;

import org.springframework.transaction.annotation.Transactional;

import com.test.spring.tx.xawl.dao.DB1jdbcDAO;
import com.test.spring.tx.xawl.dao.DB2jdbcDAO;

public class BuzSingleService {
	private DB1jdbcDAO db1;
    private DB2jdbcDAO db2;
    @Transactional(value="transactionManager",rollbackFor=Exception.class)
    public void testTX1() throws Exception {
    	db1.testInsert(0, "db1jdbcDAO val0");
        db2.testInsert(0, "db2jdbcDAO val0");
       
    }
	public DB1jdbcDAO getDb1() {
		return db1;
	}
	public void setDb1(DB1jdbcDAO db1) {
		this.db1 = db1;
	}
	public DB2jdbcDAO getDb2() {
		return db2;
	}
	public void setDb2(DB2jdbcDAO db2) {
		this.db2 = db2;
	}
    
    
}

5,controller层:

package com.test.spring.tx.xawl.controller;

import java.util.Date;

import javax.jms.Destination;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.inspur.ahDqyJMS.service.ProducerServiceImpl;
import com.test.spring.tx.xawl.Service.BuzSingleService;

@Controller
@RequestMapping("testJTA")
public class TestControllerJTA {

	@Autowired
	private BuzSingleService buzSingleService;
	
	@RequestMapping("first")
	public  void first() {
		try {
			buzSingleService.testTX1();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
}

6,在浏览器输入http://localhost:7001/SpringJMS/testJTA/first.do在两个数据库中正常插入数据.,如果将testTX1改为如下,两个数据库中都不会有数据插入.

 public void testTX1() throws Exception {
    	db1.testInsert(0, "db1jdbcDAO val0");
        db2.testInsert(0, "db2jdbcDAO val0");
        
        String nullStr = null;
        nullStr.length();
    }

遇到的问题及解决方案:

问题一:异常描述:weblogic.transaction.TimedOutException: Transaction timed out after 40 seconds 

原因分析:超时秒数: 指定在两阶段提交事务处理中允许活动事务处理处于第一阶段的最长时间 (秒)。如果指定的时间到期, 则将自动回退该事务处理。默认的是30秒 

解决方法:

登陆AdminConsole 
Environments --> <DomainName> (ClickHere) ---> Configuration (Tab) ---> JTA (SubTab) ----> in this page try to set the Transcation timeout 

将该值设大一点,我设成了600秒,一般不会超过这么多了,超过的话说明代码需要优化。 

设置完   保存成功后   不需要重启  就会生效。 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李晓LOVE向阳

你的鼓励是我持续的不断动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值