TeaFramework——事务的实现


声明:本文转载自https://my.oschina.net/u/1778239/blog/1584805,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

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

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

    对于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();  }

    执行结果:

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

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

本文发表于2017年12月05日 10:33
(c)注:本文转载自https://my.oschina.net/u/1778239/blog/1584805,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1781 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1