Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / JFinal - 事务实现的原理

使用声明式事务

事务类本身就是一个拦截器,可以用注解的方式配置。方法内部的所有 DML 操作都将在本次事务之内。配置代码如下:@Before(Tx.class)public void savePost(){//...}事务配置就是这么简单任性。

声明式事务实现原理

上述配置中为 savePost() 配置了事务也就是拦截器 Tx,当调用到 savePost() 的时候,是会进入到 Tx 的 intercept 方法中的:
  1. 建立数据库连接;
  2. 设置事务隔离级别;
  3. 设置事务手动提交;
  4. 反射机制调用 savePost();
  5. 事务提交;
  6. 若事务失败,就回滚。
主要代码如下:public void intercept(Invocation inv) {Config config = getConfigWithTxConfig(inv);if (config == null)config = DbKit.getConfig();Connection conn = config.getThreadLocalConnection();// 下面这段支持嵌套事务,可以忽略不看if (conn != null) {try {if (conn.getTransactionIsolation() < getTransactionLevel(config))conn.setTransactionIsolation(getTransactionLevel(config));inv.invoke();return ;} catch (SQLException e) {throw new ActiveRecordException(e);}}Boolean autoCommit = null;try {// 1. 建立数据库连接conn = config.getConnection();autoCommit = conn.getAutoCommit();config.setThreadLocalConnection(conn);// 2. 设置事务隔离级别conn.setTransactionIsolation(getTransactionLevel(config));// conn.setTransactionIsolation(transactionLevel);// 3. 设置事务手动提交conn.setAutoCommit(false);// 4. 反射机制调用 savePost()inv.invoke();// 5. 事务提交conn.commit();} catch (NestedTransactionHelpException e) {if (conn != null) try {conn.rollback();} catch (Exception e1) {LogKit.error(e1.getMessage(), e1);}LogKit.logNothing(e);} catch (Throwable t) {// 6. 若有异常就回滚if (conn != null) try {conn.rollback();} catch (Exception e1) {LogKit.error(e1.getMessage(), e1);}throw t instanceof RuntimeException ? (RuntimeException)t : new ActiveRecordException(t);}finally {try {if (conn != null) {if (autoCommit != null)conn.setAutoCommit(autoCommit);conn.close();}} catch (Throwable t) {LogKit.error(t.getMessage(), t);// can not throw exception here, otherwise the more important exception in previous catch block can not be thrown}finally {config.removeThreadLocalConnection();// prevent memory leak}}} 

事务隔离级别

Tx.java 使用的是 JFinal 默认配置的事务隔离级别,是在 DbKit.java 中配置的public static final int DEFAULT_TRANSACTION_LEVEL = Connection.TRANSACTION_REPEATABLE_READ;JFinal 还有几个拦截器,可以根据事务隔离级别的需求选用。它们都继承与 Tx.java,唯一不同的就是事务隔离级别。以 TxReadCommitted 为例。继承 Tx.java,覆盖了 getTransactionLevel 方法,返回常量值,这个常量就代表了事务隔离级别。public class TxReadCommitted extends Tx {/** * A constant indicating that * dirty reads are prevented; non-repeatable reads and phantom * reads can occur.This level only prohibits a transaction * from reading a row with uncommitted changes in it. */private int TRANSACTION_READ_COMMITTED = 2;@Overrideprotected int getTransactionLevel(com.jfinal.plugin.activerecord.Config config) {return TRANSACTION_READ_COMMITTED;}} 

另一种实现事务的方式

这种实现方式并没有使用拦截器。跟踪代码最终追到 DbPro.java 如下代码中:boolean tx(Config config, int transactionLevel, IAtom atom) {Connection conn = config.getThreadLocalConnection();if (conn != null) {// Nested transaction supporttry {if (conn.getTransactionIsolation() < transactionLevel)conn.setTransactionIsolation(transactionLevel);boolean result = atom.run();if (result)return true;throw new NestedTransactionHelpException("Notice the outer transaction that the nested transaction return false");// important:can not return false}catch (SQLException e) {throw new ActiveRecordException(e);}}Boolean autoCommit = null;try {// 1. 建立数据库连接conn = config.getConnection();autoCommit = conn.getAutoCommit();config.setThreadLocalConnection(conn);// 2. 设置事务隔离级别conn.setTransactionIsolation(transactionLevel);// 3. 设置事务手动提交conn.setAutoCommit(false);// 4. 所有 DML 操作是否都执行成功?boolean result = atom.run();// 5. 都成功:提交;不是都成功:回滚if (result)conn.commit();elseconn.rollback();return result;} catch (NestedTransactionHelpException e) {if (conn != null) try {conn.rollback();} catch (Exception e1) {LogKit.error(e1.getMessage(), e1);}LogKit.logNothing(e);return false;} catch (Throwable t) {if (conn != null) try {conn.rollback();} catch (Exception e1) {LogKit.error(e1.getMessage(), e1);}throw t instanceof RuntimeException ? (RuntimeException)t : new ActiveRecordException(t);} finally {try {if (conn != null) {if (autoCommit != null)conn.setAutoCommit(autoCommit);conn.close();}} catch (Throwable t) {LogKit.error(t.getMessage(), t);// can not throw exception here, otherwise the more important exception in previous catch block can not be thrown} finally {config.removeThreadLocalConnection();// prevent memory leak}}}主要事务流程:
  1. 建立数据库连接;
  2. 设置事务隔离级别;
  3. 设置事务手动提交;
  4. 调用 Atom 的 run 方法,所有 DML 操作是否都执行成功? 若都成功则事务提交,反之事务回滚。
Jfinal学习之路---Controller使用 http://www.linuxidc.com/Linux/2014-07/104323.htmJFinal开发8个常见问题 http://www.linuxidc.com/Linux/2015-02/113421.htmJFinal的详细介绍:请点这里
JFinal的下载地址:请点这里本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-09/135252.htm