`

对多数据源进行aop声明式事务管理

阅读更多
当在对数据库表进行横向切分(将一个表的数据拆分为到多个数据库中)之后, 在操作数据库的时候需要路由到合适的数据源, 这里我参照了Spring对多数据源的路由处理方式(http://blog.springsource.com/2007/01/23/dynamic-datasource-routing). 具体实现如下.
首先是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
 * 
 * @since 2009-10-28 下午01:54:46
 */
@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类
 * 
 * @since 2009-10-28 下午01:34:11
 * @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);
3
1
分享到:
评论

相关推荐

    Hibernate编程式事务与Spring Aop的声明式事务(spring与hibernate集成)

    本篇文章将重点讨论如何在Spring框架中集成Hibernate,并探讨编程式事务管理和Spring AOP的声明式事务。 首先,让我们理解Spring与Hibernate的集成。为了整合这两个库,你需要在Spring配置文件中定义Hibernate的...

    SpringMVC配置多数据源实战

    - 在实际业务中,可能需要根据具体需求对数据源进行更复杂的管理,如读写分离、负载均衡等。 - 事务管理器的选择需考虑性能和兼容性,如Hibernate的JpaTransactionManager或Spring的DataSourceTransactionManager...

    Spring多数据源分布式事务管理

    最后,通过@TransactionManagement注解开启Spring的声明式事务管理,并使用@Transactional注解来指定事务边界。 接下来,我们要关注的是Druid和MyBatis在多数据源环境中的应用。Druid是一个优秀的数据库连接池,它...

    Spring Data JPA系列4——Spring声明式事务处理与多数据源支持.doc

    Spring 声明式事务处理与多数据源支持 在大部分涉及到数据库操作的项目里面,事务控制、事务处理都是一个无法回避的问题。Spring 框架提供了声明式事务处理机制,使得业务代码中进行事务控制操作起来非常简单。只需...

    SpringBoot+Atomikos+动态多数据源+事务+2种切换数据源的方式

    - **声明式切换**:通过AOP切面或者自定义注解,可以在方法执行前切换数据源。例如,可以创建一个`@SwitchDataSource`注解,定义目标数据源,然后编写切面逻辑来处理这个注解,改变`AbstractRoutingDataSource`的...

    spring3,hibernate4 配置声明式事务管理(annotation方式)

    然后,启用Spring的AOP代理和声明式事务管理。在配置文件中加入以下内容: ```xml &lt;aop:config&gt; &lt;aop:pointcut id="serviceMethods" expression="execution(* com.example.service.*.*(..))"/&gt; &lt;aop:advisor ...

    spring声明式事务处理demo

    编程式事务管理通常通过AOP(面向切面编程)的TransactionTemplate或PlatformTransactionManager接口直接在代码中控制事务,而声明式事务管理则是基于AOP的,通过配置XML或使用注解来定义事务边界。 1. **配置...

    spring编程式和声明式事务管理

    编程式事务管理适合对事务有特殊需求或需要精细控制的场合,而声明式事务管理则更适合大部分常规情况,让代码更加整洁。在实际项目中,根据具体需求和团队习惯来选择合适的事务管理方式是非常重要的。

    Spring 整合mybatis(注解&xml版声明式事务).pdf

    如果采用XML配置方式,则需要在Spring的XML配置文件中进行事务配置,并通过aop命名空间来定义事务通知及切点,从而实现声明式事务管理。 对于开发者而言,Spring与MyBatis的整合简化了事务和持久层的处理,减少了...

    springboot+mybat(多数据源) 通过aop实现分库的操作 ,通过传入的动态表明实现分表查询

    在SpringBoot中,我们可以通过声明式的方式配置数据源,例如通过`application.properties`或`application.yml`文件,定义多个数据源连接信息。 接下来,我们引入MyBatis作为持久层框架。MyBatis允许我们编写SQL语句...

    多数据源事物控制

    在事务管理方面,Spring提供了声明式事务管理,使得开发者无需手动管理事务的开始、提交、回滚等操作,只需在配置中指定事务边界即可。 MyBatis是一个轻量级的持久层框架,它简化了数据库操作,允许开发者通过SQL...

    Spring 2.5整合iBATIS 2.3并使用Spring的声明式事务管理

    7. **声明式事务管理**:Spring提供了声明式事务管理,我们可以在方法级别或类级别通过@Transactional注解来控制事务的边界。例如: ```java @Service public class UserService { @Autowired private UserMapper...

    声明式事务1

    要使用声明式事务,需要先搭建环境,包括导入相关依赖、配置数据源和 JdbcTemplate、给方法上标注 @Transactional、开启基于注解的事务管理功能、配置事务管理器等步骤。 1. 导入相关依赖:需要导入 Spring-jdbc ...

    实验 spring 声明事务

    在Spring中,声明式事务管理依赖于AOP(面向切面编程)来实现。首先,需要配置一个事务管理器,通常使用`DataSourceTransactionManager`,它与数据源`dataSource`关联。然后,通过`&lt;tx:annotation-driven&gt;`标签启用...

    spring 事务管理例子(TransactionProxyFactoryBean代理机制 和 tx/aop)

    在这个例子中,我们将聚焦于Spring的声明式事务管理,特别是通过`TransactionProxyFactoryBean`代理机制以及`@Transactional`注解与AOP(面向切面编程)的结合使用。 首先,`TransactionProxyFactoryBean`是Spring...

    Spring使用XML配置声明式事务

    在Spring框架中,声明式事务管理是实现事务处理的一种高效且灵活的方式,它允许开发者通过XML配置或注解来定义事务边界,而无需在业务逻辑代码中显式地调用开始、提交或回滚事务的方法。这篇博文"Spring使用XML配置...

    java多数据源代码实例

    2. 事务管理需要考虑到数据源切换,可以通过编程式事务管理或声明式事务管理实现。 五、代码实例 在实际项目中,可以创建两个数据库连接池(如HikariCP或Druid),然后根据业务需求在Service层或Controller层切换...

    SSM多数据源分包

    在多数据源环境下,Spring的声明式事务管理需要特别注意。因为不同的数据源可能需要不同的事务隔离级别和回滚规则,所以我们需要配置多个PlatformTransactionManager,并根据数据源路由结果选择合适的事务管理器。 ...

    spring+ibatis声明式事务Demo_

    **声明式事务管理** 是Spring提供的事务管理方式之一,主要通过AOP实现。在Spring中,可以使用`@Transactional`注解在方法级别声明事务边界。当该方法执行时,Spring会自动处理事务的开启、提交或回滚,这极大地简化...

Global site tag (gtag.js) - Google Analytics