TeaFramework——事务的实现

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

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

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

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

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

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

    二、事务的传播编码

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

    请看具体的代码线程

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的思路来实现debug

    一、before:在事务开启以前,获取数据库链接,并设置自动提交为false代理

    二、after:执行过程若是没有任何异常,则提交事务

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

    四、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();

}

    执行结果:

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

     项目地址:https://git.oschina.net/lxkm/teaframework
     博客:https://my.oschina.net/u/1778239/blog 

相关文章
相关标签/搜索