事务的本质:让程序像咱们看到的那样执行。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