运行环境:JDeveloper 11.1.2.2.0 + Oracle Database 10g Express Edition 10.2.0.1。
ADF TaskFlow的Transaction与数据库的Transaction的原理不同。
ADF TaskFlow的Transaction是在控制器层的,数据库的Transaction是在数据层的。
ADF TaskFlow的Transaction与Java EE的Transaction的原理也不同。
Java EE的Transaction是由Container管理事务,因此如果在TaskFlow中调用一个带事务批注的EJB方法,二者无法在同一个事务之中。
我们知道,ADF Model层可以生成Data Control,而每个ADF TaskFlow与一个Data Control Frame相关联。
一个Data Control Frame是一个容器,它负责管理与该TaskFlow相关联的多个Data Control实例。
同在一个Data Control Frame中的Data Control实例是在一个事务中的。
DataControlFrame Interface有如下方法:
(1)beginTransaction()
(2)commit()
(3)rollback()
(4)createSavepoint()
(5)isTransactionDirty()
在TaskFlow的Transaction的设置中,还有一个重要的属性:Share Data Control with Calling TaskFlow。
Transaction与Share Data Control之间的关系如下:
(1)Transaction=No Controller Transaction
选中Share Data Control,没有事务的父与子TaskFlow共享Data Control Frame中的Data Control实例;
未选中Share Data Control,没有事务的父与子TaskFlow各自创建和使用各自的Data Control Frame中的Data Control实例。
(2)Transaction=Always begin new transaction
选中Share Data Control,如果已经有了一个事务,抛出异常,否则,开始一个新事务;
未选中Share Data Control,开始一个新事务,无论是否已经有了一个事务。
(3)Transaction=Always Use Existing Transaction
选中Share Data Control,如果没有事务,抛出异常;
未选中Share Data Control,此时本选项无效。
(4)Transaction=Use Existing Transaction if Possible
选中Share Data Control,如果没有事务,开始一个新事务,否则使用已有的事务;
未选中Share Data Control,开始一个新事务,无论是否已经有了一个事务。
下面举一例说明:
3个BTFs,A调用B,B调用C。A和B使用同一个Data Control Frame(即同一个AM),而C使用不同的Data Control Frame(即另一个AM)。
如果选中Share Data Control(默认情况下是选中的),当进入BTF A时,首先创建A的Data Control实例;A调用B,进入BTF B时,不会再创建新的Data Control实例,而是使用A的Data Control实例。
当B调用C,进入BTF C时,因为与A和B的Data Control Frame不同,所以会创建C的Data Control实例;虽然使用的是不同的Data Control实例,但ADF会把C的Data Control实例交由A的Data Control实例管理,类似于嵌套的AM。
选中Share Data Control的好处是多个BTFs可以使用同一个数据库连接。
最后用一个Project来说明选中和未选中Share Data Control的区别。
1. 设计说明(1)main.jsf页面中有一个Region,一个InputText,用于输入,一个按钮,调用方法hello(),另一个InputText,显示输出。
(2)jobs.jsff页面中有一个Table,一个按钮,也调用方法hello(),一个InputText,显示输出。
(3)hello()方法是定义在AM中的,暴露给Client Interface。
(4)TaskFlow的定义中,Share Data Control默认是选中的(蓝色的小方块)。
2. 运行(1)点击Call hello inside BTF,jobs.jsff页面中的InputText显示了新的值。
(2)为Greeting InputText输入一个值,然后点击Call hello outside BTF,发现jobs.jsff页面中的InputText和main.jsf页面中InputText的都显示了同样的新的值。
3. 修改TaskFlow的定义中,设置Share Data Control=false4. 再次运行为Greeting InputText输入一个值,然后点击Call hello outside BTF,这次发现只有main.jsf页面中InputText的显示了新的值,而jobs.jsff页面中的InputText没有改变。
实验小结:当设置设置Share Data Control=false后,子TaskFlow不再使用父TaskFlow的Data Control实例,而是创建自己的实例。因此,虽然绑定的依然是hello()方法的返回值,但是不是同一个实例。
Project 下载:
ADF_TaskFlow_ShareDataControl.7z参考文献:
1. http://jjzheng.blogspot.com/2011/03/does-your-task-flow-need-transaction.html
2. http://xmlandmore.blogspot.com/2010/03/understanding-task-flow-transaction-and.html
3. http://tompeez.wordpress.com/2012/07/27/jdeveloper-adf-carefully-select-the-data-control-scope-of-bounded-task-flows/
4. http://andrejusb.blogspot.com/2011/08/adf-dialog-framework-and-adf-task-flow.html