事务的实现
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
事務(wù)的本質(zhì):讓程序像我們看到的那樣執(zhí)行。
? ? 數(shù)據(jù)庫事務(wù)就是對于界定為同一個事務(wù)的一組數(shù)據(jù)庫操作,要么同時成功,要么同時失敗,不可能出現(xiàn)部分成功的中間狀態(tài)。
? ? 對于JDBC原生事務(wù),首先要設(shè)置自動提交為false:connection.setAutoCommit(false),如果整個執(zhí)行過程沒有異常則提交事務(wù)commit,否則就回滾rollback。對于原生態(tài)的jdbc事務(wù),編碼顯得非常繁瑣,并且對于整個系統(tǒng)的共性業(yè)務(wù),特別適合用AOP的方式來實(shí)現(xiàn)。
? ? 下面說到重點(diǎn)了,TeaFramework事務(wù)實(shí)現(xiàn)。
? ? 1、事務(wù)的使用應(yīng)該盡量簡單,在方法或者class上加一個注解便可搞定,對于class有事務(wù)注解,那么該class所有方法都有進(jìn)行事務(wù)控制。
@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface Transcation { }? ? 2、事務(wù)的傳播
? ? 事務(wù)的傳播描述的是多個事務(wù)嵌套的問題,對于大部分場景而言,頂層方法有事務(wù),則子事務(wù)被納入當(dāng)前事務(wù),這種場景占80%,那么TeaFramework只實(shí)現(xiàn)這種事務(wù)傳播。
? ? 請看具體的代碼
public class TranscationProxy extends AbstractProxy {private Logger logger = LoggerFactory.getLogger(getClass());@Overridepublic 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注解則進(jìn)入try {before(proxy);proxy.invoke(proxy);after(proxy);} catch (Throwable e) {exception(proxy);throw e;} finally {end(beanProxy);}} else {proxy.invoke(proxy);}}@Overridepublic void before(Proxy proxy) {try {TranscationThreadVariable.set(true);logger.debug("開啟事務(wù)");if (ConnectionThreadVariable.getConnetion() == null) {Connection connection = DataSourceHelp.getConnection();connection.setAutoCommit(false);ConnectionThreadVariable.setConnetion(connection);}} catch (Exception e) {throw new TranscationException(e);}}@Overridepublic void after(Proxy proxy) {try {logger.debug("提交事務(wù)");ConnectionThreadVariable.getConnetion().commit();} catch (Exception e) {throw new TranscationException(e);}}@Overridepublic void exception(Proxy proxy) {try {logger.debug("回滾事務(wù)");ConnectionThreadVariable.getConnetion().rollback();} catch (Exception e) {throw new TranscationException(e);}}@Overridepublic void end(Proxy proxy) {try {logger.debug("關(guān)閉連接");ConnectionThreadVariable.getConnetion().close();} catch (Exception e) {throw new TranscationException(e);} finally {ConnectionThreadVariable.clearThreadVariable();TranscationThreadVariable.clearThreadVariable();}}}? ? 這里本質(zhì)上是實(shí)現(xiàn)了一個代理類,用AOP的思路來實(shí)現(xiàn)
? ? 1、before:在事務(wù)開啟之前,獲取數(shù)據(jù)庫連接,并設(shè)置自動提交為false
? ? 2、after:執(zhí)行過程如果沒有任何異常,則提交事務(wù)
? ? 3、exception:執(zhí)行過程發(fā)生異常,則回滾事務(wù)
? ? 4、end:執(zhí)行結(jié)束,關(guān)閉數(shù)據(jù)庫連接,歸還給連接池
? ? 那么事務(wù)的傳播在哪里實(shí)現(xiàn)的呢?僅僅只有一行代碼TranscationThreadVariable.set(true),這行代碼標(biāo)示了當(dāng)前線程中事務(wù)的狀態(tài),如果事務(wù)已經(jīng)由上層方法開啟,則下面所有的數(shù)據(jù)庫操作與開啟事務(wù)的方法共用一個數(shù)據(jù)庫連接connection,那么就被納入了一個事務(wù)。
? ? 來看一個例子,在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);@DynamicSQLpublic int update();@SQL("delete from users")public int deleteUserById();@SQL("select * from users")public List<User> getAllUser();@DynamicSQLpublic List<User> findUser();}? ? 執(zhí)行結(jié)果:
? ? 這就是TeaFramework事務(wù)的實(shí)現(xiàn)過程。
轉(zhuǎn)載于:https://my.oschina.net/architectliuyuanyuan/blog/1611442
總結(jié)
- 上一篇: 对GC垃圾收集的一点整理
- 下一篇: Hive JDBC:Permission