Spring 多数据源声明式事务控制(PlatformTransactionManager )

标签: spring 数据 控制 | 发表时间:2014-04-11 18:31 | 作者:cn-done
出处:http://www.iteye.com
 
首先是TransactionManager的配置:
<?xml version="1.0" encoding="gb2312"?>
<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:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
	<bean id="db1Tx"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
            <ref bean="db1" />
		</property>
	</bean>

	<bean id="db2Tx"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
			<ref bean="db2" />
		</property>
	</bean>

	<bean id="dbcTx"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
		      <ref bean="dbc" />
		</property>
	</bean>

	<bean id="routingTransactionManager" class="com.mysoft.manager.impl.RoutingTransactionManager">
		<property name="targetTransactionManagers">
			<map value-type="org.springframework.transaction.PlatformTransactionManager">
				<entry key="db1" value-ref="db1Tx" />
				<entry key="db2" value-ref="db2Tx" />
				<entry key="dbc" value-ref="dbcTx" />
			</map>
		</property>
	</bean>

	<!--     配置事务回滚的场景   -->
	<tx:advice id="txAdvice" transaction-manager="routingTransactionManager">
		<tx:attributes>
            		<tx:method name="*" rollback-for="java.lang.Exception"/>
		</tx:attributes>
	</tx:advice>
	
	<!--   指定那些类的哪些方法参与事务   -->
	<aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.mysoft.manager.Manager1.publish(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.mysoft.manager.Manager2.audit(..))"/>
	</aop:config>
</beans>
 这里用到了spring的tx和aop标签, 都是spring的参考手册中的典型配置. 当调用指定的packageName.method(..)方法的时候, 将采用事务拦截, 如果在对该方法的调用过程中出现了任何异常将导致事务回滚.

接下来就是路由的问题, 其中RoutingContextHolder类内部使用一个ThreadLocal类用来指定db1, db2, db3等key值, RoutingTransactionManager类则根据当前线程中的key值取得对应的tx.
/**
* 用来存储路由到指定tx的Context
 * 
 */
@SuppressWarnings("unchecked")
public class RoutingContextHolder<T> {
    private static final ThreadLocal contextHolder = new ThreadLocal();

    public static <T> void setContext(T context) {
        Validate.notNull(context, "必须指定路由的context");
        contextHolder.set(context);
    }

    public static <T> T getContext() {
        return (T) contextHolder.get();
    }
}
 
/**
* 根据给定的路由规则来路由到合适的tx类
 * 
 * @see RoutingContextHolder
 */
public class RoutingTransactionManager implements PlatformTransactionManager {
    private Map<Object, PlatformTransactionManager> targetTransactionManagers =
            new HashMap<Object, PlatformTransactionManager>();

    /**
     * 根据给定的规则获取指定的tx
     * 
     * @return
     */
    protected PlatformTransactionManager getTargetTransactionManager() {
        Object context = RoutingContextHolder.getContext();
        Validate.notNull(context, "必须指定路由的context");
        return targetTransactionManagers.get(context);
    }

    public void setTargetTransactionManagers(Map<Object, PlatformTransactionManager> targetTransactionManagers) {
        this.targetTransactionManagers = targetTransactionManagers;
    }

    public void commit(TransactionStatus status) throws TransactionException {
        getTargetTransactionManager().commit(status);
    }

    public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
        return getTargetTransactionManager().getTransaction(definition);
    }

    public void rollback(TransactionStatus status) throws TransactionException {
        getTargetTransactionManager().rollback(status);
    }
}
 其调用代码如下:
// 指定tx的路由context
RoutingContextHolder.setContext("db1");
return manager1.publish(item);
  


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [spring 数据 控制] 推荐:

Spring 多数据源声明式事务控制(PlatformTransactionManager )

- - 开源软件 - ITeye博客
首先是TransactionManager的配置:. 配置事务回滚的场景 -->. .  这里用到了spring的tx和aop标签, 都是spring的参考手册中的典型配置. 当调用指定的packageName.method(..)方法的时候, 将采用事务拦截, 如果在对该方法的调用过程中出现了任何异常将导致事务回滚.

Spring配置多数据源

- - ITeye博客
首先在配置文件中配置多个dataSource. 扩展Spring的AbstractRoutingDataSource抽象类,实现动态数据源. AbstractRoutingDataSource中的抽象方法determineCurrentLookupKey是实现数据源的route的核心.这里对该方法进行Override.

Spring多数据源事务

- - 掘金后端
接着上一篇文章 Spring事务基础,本文主要是关于Spring多数据源的情况下如何保证事务正常回滚. 这里也是使用大家广泛使用的 jta-atomikos进行,我只是做一些总结方便以后自己直接拿来用. 如果你非常着急,那么可以直接下载这个项目看看即可:. 网上已经有很多关于jta-atomikos的相关文章,本文可能有点绕,不容易看得懂,所以在此描述一下思路:.

Spring Cloud版本控制和灰度starter-spring-cloud-gray

- -
Spring Cloud Gray - 微服务灰度中间件. Spring Cloud Gray 是一套开源的微服务灰度路由解决方案,它由spring-cloud-gray-client,spring-cloud-gray-client-netflix 和 spring-cloud-tray-server,spring-cloud-gray-webui组成.

spring+hibernate多数据源的应用

- - CSDN博客推荐文章
我有两个数据库test,和test1,两个库里都有一张表TEST_ONE. applicationContext.xml的配置如下. //数据库test1配置.   //整合两个数据源,指定数据源管理类.    //数据库test.    //数据库test1. //这个类是用来管理数据源的,配置文件中.

Spring+MyBatis实践——MyBatis访问数据库

- - 开源软件 - ITeye博客
    在http://dufengx201406163237.iteye.com/blog/2102054中描述了工程的配置,在此记录一下如何使用MyBatis访问数据库;. . .

spring实现数据库读写分离

- - 行业应用 - ITeye博客
现在大型的电子商务系统,在数据库层面大都采用读写分离技术,就是一个Master数据库,多个Slave数据库. Master库负责数据更新和 实时数据查询,Slave库当然负责非实时数据查询. 因为在实际的应用中,数据库都是读多写少(读取数据的频率高,更新数据的频率相对较少),而读取数据 通常耗时比较长,占用数据库服务器的CPU较多,从而影响用户体验.

Spring多数据源的配置

- - 编程语言 - ITeye博客
在大型的应用中,为了提高数据库的水平伸缩性,对多个数据库实例进行管理,需要配置多数据源. 在Spring框架被广泛运用的今天,可以很简单的运用Spring中的特性配置动态多数据. 首先配置一个基于c3p0.ComboPooledDataSource的数据源A. 接着扩展一个Spring提供的AbstractRoutingDataSource,Override 其中的 determineCurrentLookupKey方法实现数据源的route.

Spring Boot使用redis做数据缓存

- - ITeye博客
SysUser.class)); //请注意这里. 3 redis服务器配置. /** *此处的dao操作使用的是spring data jpa,使用@Cacheable可以在任意方法上,*比如@Service或者@Controller的方法上 */ public interface SysUserRepo1 extends CustomRepository {.

Spring MVC防止数据重复提交

- - 编程语言 - ITeye博客
来讲一下如何在Spring MVC里面解决此问题(其它框架也一样,逻辑一样,思想一样,和具体框架没什么关系). 要解决重复提交,有很多办法,比如说在提交完成后redirect一下,也可以用本文提到的使用token的方法(我不使用redirect是因为那样解决不了ajax提交数据或者移动应用提交数据,另一个原因是现在比较通行的方法是使用token,像python里的django框架也是使用token来解决).