Dorado 5 : 9.3.事务管理 (RF1)

概述

Dorado中提供了JDBC的轻量级封装.在事务管理层,dorado将事务委托给底层的JDBC或则JTA,以实现事务的管理和调度。
Dorado默认的事务处理机制基于JDBCTransaction。我们也可以定义自己的Transaction对象,通过配置自定义实现事务管理,在setting.xml中:

<?xml version="1.0" encoding="UTF-8"?>
<properties>
......
<property name="common.transactionHandler" value="com.bstek.dorado.common.JDBCTransaction"/>
......
</properties>

JDBC事务管理机制

Dorado自身提供了基于JDBC的事务管理机制,在通常使用DBDataset以及DBStatement等类维护数据库的时候,开发人员并不需要编写代码管理事务,dorado会自动的根据需要创建和管理事务。当用户进行了一系列的数据更新动作,Dorado会保证所有操作的原子性与一致性。但是,在某些情况下,用户希望自己管理事务,在dorado中也提供了相关的事务管理类以及事务管理相关的API,如:commit(), rollback()等。
将事务委托给JDBC处理非常简单,dorado中处理JDBC的代码如下:

Transaction trans = TransactionManager.getTransaction();
trans.beginTransaction();
......
trans.commit();

以上代码与JDBC底层调用对应的代码就是:

Connection conn = getConnection();
conn.setAutoCommit(false);
......
conn.commit();

Dorado本身并没有作特别多的事,其中com.bstek.dorado.common.Transaction对象为Dorado中事务管理的代理对象,通过com.bstek.dorado.common.TransactionManager类获取。
Transaction提供getConnection方法获取java.sql.Connection对象:

Connection conn = trans.getConnection();

这里需要注意的是,当获取Connection对象时,内部会根据是否已经启动beginTransaction()决定设置autoCommint为false,如未启动,就设定为true,否则就是false,而其后,在trans.beginTransaction()方法中,dorado会自动的将其中的Connection对象的autoCommit属性设置为false。
这也就是说,如果不启动事务,下面的代码会马上提交到数据库:

Statement stmt = conn.createStatement();
stmt.executeUpdate("update dept set branch_id='D2' where dept_id='D11'");
conn.close();

而如果调用了beginTransaction()方法,Transaction就会自动检查可管理的Connection并且将connection的AutoCommit设置为false,则上面的Statement调用代码不会产生任何效果。

JTA事务管理办法

由于JTA提供了跨越多个数据库和进程的事务管理机制,部分系统在愿意付出性能代价的前提下支持JTA事务。
Dorado也支持JTA事务管理方式,因为默认情况下dorado使用的都是JDBC事务处理机制。因此如果要使dorado默认支持JTA事务管理机制就有必要在dorado默认提交机制中处理JTA事务,dorado的setting.xml文件中提供了如下的配置信息:

<property name="view.defaultViewModel" value="com.bstek.dorado.view.impl.DynaViewModel"/>

修改该配置,使用自定义的视图模型实现类,并覆盖DynaViewModel 中的doUpdate方法:

protected void doUpdateData(ParameterSet parameters)
throws Exception {
UserTransaction tx = (UserTransaction)(new InitialContext().lookup(""));
doUpdateData(parameters, null);
tx.commit();
}

加入对javax.transaction.UserTransaction管理。这样事实上我们引入了JTA中的UserTransaction以实现doUpdateData方法中的事务性。

UpdateCommand的事务配置

当使用updateCommand来做一组Dataset的数据提交时,可以通过配置设定数据提交的事务特性,UpdateCommand的属性transactionMode用来配置事务特性,该属性值定义在TransactionMananger类中,有四种,默认为TRANSACTON_REQUIRED。
TRANSACTION_NOT_SUPPORTED:not_supported,不支持事务。如果在当前线程中存在事务,则在进行该处操作前提交自动提交线程中的事务。
TRANSACTION_REQUIRED:required,需要事务。如果当前线程中存在事务,那么该处操作参与到当前线程的事务中;如果当前线程中没有事务,那么为该处操作启动一个新的事务。
TRANSACTION_REQUIRES_NEW:requires_new,需要新事务。如果当前线程中存在事务,那么提交当前线程中的事务,同时为该处操作启动一个新的事务。
TRANSACTION_SUPPORTS:supports,支持事务。如果当前线程中存在事务,那么该处操作参与到当前线程的事务中,否则,该处操作不支持事务。
Dorado中,用户进行一个动作,比如一次数据加载,一次数据更新等,就会启动一个线程,一个动作内涉及到的所有操作都会在同一个线程内,这个线程对于这些操作来说就是当前线程。

DBStatement事务

在上一节DBStatement中指出,使用DBStatement所作的数据操作可以直接参与到Dorado的当前线程的事务中。
DBStatement的事务管理模式是supports类型的,即支持事务。如果当前线程中存在事务,那么该处操作参与到当前线程的事务中,否则,该处操作不支持事务。
DBStatement使用的还是JDBCTransaction实现connection管理的:

Transaction trans = TransactionManager.getTransaction();
Connection conn = trans.getConnection();

其中Connection的事务处理可以参考上文中的基于JDBC的事务处理机制