事務的本質:讓程序像咱們看到的那樣執行。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