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 

相關文章
相關標籤/搜索