您的位置:首页 > 其它

TransactionProxyFactoryBean声明式事务

2015-09-16 11:35 441 查看
<bean id="hibernateTransProxy" abstract="true" lazy-init="true"

class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<property name="transactionManager">

<ref bean="hibernateTransManager" />

</property>

<property name="transactionAttributes">

<props>

<!--

transactionAttributes属性可以设置事务处理的方式,事务隔离级别,是否只读三个属性,用逗号隔开

事务隔离级别各数据库系统不完全支持,一般不设置,用默认的即可

事务处理选项有如下几个:(前面2个常用)

PROPAGATION_REQUIRED
- 需要事务处理。如果当前不存在事务环境,则创建一个

PROPAGATION_SUPPORTS
- 如果当前存在事务环境,则作为其中的一部分。如果不存在,则按非事务方式执行

PROPAGATION_REQUIRES_NEW
- 需要事务处理。并总是开启一个新事务。如果已经存在事务环境,则挂起之

PROPAGATION_MANDATORY
- 执行到指定方法时,必须已经存在事务环境,否则出错

PROPAGATION_NEVER
- 不支持事务操作,如果存在事务环境会出错

PROPAGATION_NOT_SUPPORTED
- 不支持事务操作。如果存在事务,则挂起

-->

<!-- find打头和get打头的方法事务处理方式为PROPAGATION_SUPPORTS,其他的采用PROPAGATION_REQUIRED -->

<!-- readOnly 表示只读事务 ;-->

<!-- -Exception 表示发生异常时回滚事务;+Exception 表示即使发生异常事务也不回滚;-->

<prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>

<prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>

<prop key="*">PROPAGATION_REQUIRED,-Exception</prop>

</props>

</property>

在使用hibernateTransProxy这个事务控制的时候,遇到的问题:

1.在一个方法执行的时候什么情况下事务会提交,什么情况下事务会回滚;

2.嵌套执行的事务提交和回滚的情况又是什么样子的;

org.springframework.transaction.interceptor.TransactionProxyFactoryBean

这个类就是以IOC为基础的面向切面编程的采用动态代理实现的声明式事务

面向切面编程:就是spring的AOP,它的思想就是在方法的调用前和方法的调用后来

做一些操作,包括日志、监控,甚至是改变方法的传入参数的值等;它的作用像管家

或者后勤,为方法的正常执行提供保障。

代理:就是控制,就像中介代理房东卖房子一样,spring替你控制,控制什么,控制bean;对于

TransactionProxyFactoryBean类来说就是控制bean的事务,而且它将事务的原子性

提高到方法这一层,而不是过去的一行代码一个事务;由此类代理的bean的一个方法

是一个事务。

声明式事务:就是说这个是由配置文件来实现的,配置在xml中,所以它是以IOC为基础的。

// ServiceClient没有事务,ServiceDAO有事务,testThrowException

// 抛出异常单独一个事务回滚,save2单独一个事务提交

public void testException() {

int result = 0;

try {

result = service.testThrowException("3", "一月又一月", "33");

} catch (Exception e1) {

e1.printStackTrace();

}

if (result == 1) {

try {

throw new Exception("ddd");

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

service.save2("2", "哈asdfas", "33");

service.save2("5", "哈哈哈", "33");

}

// ServiceClient没有事务,ServiceDAO有事务,testTryCatchException

// 捕获异常单独一个事务提交,save2单独一个事务提交

public void testTryCatchException() {

int result = 0;

result = service.testTryCatchException("3", "一月又一月", "33");

if (result == 1) {

try {

throw new Exception("ddd");

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

service.save2("2", "哈asdfas", "33");

service.save2("5", "哈哈哈", "33");

}

所以,问题1答案是:一个方法调用捕获异常,已经执行的持久化仍然提交;抛出异常持久化

将被回滚。同时应该注意如果持久化的方法以find和get打头,不管是否抛出异常

事务都不会回滚。

问题2实际上是有关事务的传播性,测试发现和在一个方法中还是不一样的。

/**

* ServiceDAO有事务 BusinessClient也有事务

*/

// save2 正常执行 save1有异常抛出 ,save1回滚 save2也会滚

public void doWorkA() throws Exception {

service.save2("2", "哈哈哈", "33");

service.save1("1", "哈hhhh哈", "33");

}

// save1 有异常抛出 ,save2 根本执行不到

public void doWorkB() throws Exception {

service.save1("2", "哈哈哈", "33");

service.save2("1", "哈hhhh哈", "33");

}

// save2 正常执行 save1有异常抛出被捕获 ,save1回滚 save2也会滚

public void doWorkC() {

service.save2("1", "哈hhhh哈", "33");

try {

service.save1("2", "哈哈哈", "33");

} catch (Exception e) {

e.printStackTrace();

}

}

// 先是doWorkD1 调用save2 正常执行 而后save1有异常抛出被捕获 ,save1回滚 save2也会滚

public void doWorkD() {

doWorkD1();

try {

service.save1("2", "哈哈哈", "33");

} catch (Exception e) {

e.printStackTrace();

}

}

public void doWorkD1() {

service.save2("1", "哈hhhh哈", "33");

}

问题2的答案是嵌套调用的情况下,只要有异常不管是捕获还是抛出,事务都会被被回滚
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: