TeaFramework——事务的实现

    事务的本质:让程序像我们看到的那样执行。

    数据库事务就是对于界定为同一个事务的一组数据库操作,要么同时成功,要么同时失败,不可能出现部分成功的中间状态。

    对于JDBC原生事务,首先要设置自动提交为false:connection.setAutoCommit(false),如果整个执行过程没有异常则提交事务commit,否则就回滚rollback。对于原生态的jdbc事务,编码显得非常繁琐,并且对于整个系统的共性业务,特别适合用AOP的方式来实现。

    下面说到重点了,TeaFramework事务实现。

    1、事务的使用应该尽量简单,在方法或者class上加一个注解便可搞定,对于class有事务注解,那么该class所有方法都有进行事务控制。

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Transcation {
}

    2、事务的传播

    事务的传播描述的是多个事务嵌套的问题,对于大部分场景而言,顶层方法有事务,则子事务被纳入当前事务,这种场景占80%,那么TeaFramework只实现这种事务传播。

    请看具体的代码

public class TranscationProxy extends AbstractProxy {
	private Logger logger = LoggerFactory.getLogger(getClass());

	@Override
	public void invoke(Proxy proxy) throws Throwable {
		BeanProxy beanProxy = (BeanProxy) proxy;
		boolean classHasTranscationAnnotation = beanProxy.getObj().getClass().getSuperclass()
				.isAnnotationPresent(Transcation.class);
		boolean methodHasTranscationAnnotation = beanProxy.getMethod().isAnnotationPresent(Transcation.class);
		if (TranscationThreadVariable.get() == null
				&& (classHasTranscationAnnotation || methodHasTranscationAnnotation)) {// 如果类或者方法有Transcation注解则进入
			try {
				before(proxy);
				proxy.invoke(proxy);
				after(proxy);
			} catch (Throwable e) {
				exception(proxy);
				throw e;
			} finally {
				end(beanProxy);
			}
		} else {
			proxy.invoke(proxy);
		}

	}

	@Override
	public void before(Proxy proxy) {
		try {
			TranscationThreadVariable.set(true);
			logger.debug("开启事务");
			if (ConnectionThreadVariable.getConnetion() == null) {
				Connection connection = DataSourceHelp.getConnection();
				connection.setAutoCommit(false);
				ConnectionThreadVariable.setConnetion(connection);
			}
		} catch (Exception e) {
			throw new TranscationException(e);
		}
	}

	@Override
	public void after(Proxy proxy) {
		try {
			logger.debug("提交事务");
			ConnectionThreadVariable.getConnetion().commit();
		} catch (Exception e) {
			throw new TranscationException(e);
		}
	}

	@Override
	public void exception(Proxy proxy) {
		try {
			logger.debug("回滚事务");
			ConnectionThreadVariable.getConnetion().rollback();
		} catch (Exception e) {
			throw new TranscationException(e);
		}
	}

	@Override
	public void end(Proxy proxy) {
		try {
			logger.debug("关闭连接");
			ConnectionThreadVariable.getConnetion().close();
		} catch (Exception e) {
			throw new TranscationException(e);
		} finally {
			ConnectionThreadVariable.clearThreadVariable();
			TranscationThreadVariable.clearThreadVariable();
		}
	}

}

    这里本质上是实现了一个代理类,用AOP的思路来实现

    1、before:在事务开启之前,获取数据库连接,并设置自动提交为false

    2、after:执行过程如果没有任何异常,则提交事务

    3、exception:执行过程发生异常,则回滚事务

    4、end:执行结束,关闭数据库连接,归还给连接池

    那么事务的传播在哪里实现的呢?仅仅只有一行代码TranscationThreadVariable.set(true),这行代码标示了当前线程中事务的状态,如果事务已经由上层方法开启,则下面所有的数据库操作与开启事务的方法共用一个数据库连接connection,那么就被纳入了一个事务。

    来看一个例子,在insert方法上加上@Transcation注解

@TeaDao("testDao")
public interface TestDao {

	@Transcation
	@GetPrimaryKey(sql = "select s_users.nextval from dual", primaryKeyProperty = "id")
	@SQL("insert into users(id,name,password,createdate) values(#id#,#name#,#password#,#createdate#)")
	public int add(Map<String, Object> map);

	@DynamicSQL
	public int update();

	@SQL("delete from users")
	public int deleteUserById();

	@SQL("select * from users")
	public List<User> getAllUser();

	@DynamicSQL
	public List<User> findUser();

}

    执行结果:

223216_sdey_1778239.png

    这就是TeaFramework事务的实现过程。

     项目地址:https://git.oschina.net/lxkm/teaframework
     博客:https://blog.csdn.net/dong_lxkm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值