【Spring.事务.异常回滚】请问Spring的声明式事务发生异常时的处理方式。
http://www.iteye.com/problems/17791
我的方法(使用伪代码表述):
Java代码
@Transactional
public 一个业务方法(){
try{
//一些业务操作,期间可能会抛出运行时异常。
int i = 3/0;
... ...
//调用A实体相关的dao方法,dao使用了Spring的DAO模版。 期间可能会出现事务冲突的问题。
aDao.oneMethod();
... ...
//一些业务操作,期间可能会抛出运行时异常。
int i = 3/0;
if(某条件){
throw new 自定义的运行时异常();
}
... ...
//调用B实体相关的dao方法,dao使用了Spring的DAO模版。 期间可能会出现事务冲突的问题。
bDao.oneMethod();
... ...
}catch(Spring异常){
//做一些自定的操作。
... ...
}
}
@Transactional
public 一个业务方法(){
try{
//一些业务操作,期间可能会抛出运行时异常。
int i = 3/0;
... ...
//调用A实体相关的dao方法,dao使用了Spring的DAO模版。 期间可能会出现事务冲突的问题。
aDao.oneMethod();
... ...
//一些业务操作,期间可能会抛出运行时异常。
int i = 3/0;
if(某条件){
throw new 自定义的运行时异常();
}
... ...
//调用B实体相关的dao方法,dao使用了Spring的DAO模版。 期间可能会出现事务冲突的问题。
bDao.oneMethod();
... ...
}catch(Spring异常){
//做一些自定的操作。
... ...
}
}
请问:
1. 在未调用dao方法之前,若出现了运行时异常,Spring还会做开启事务、关闭事务的动作吗?
2. 在调用aDao.oneMethod()之后、bDao.oneMethod()之前,出现运行时异常,会导致事务回滚吗?
3. 若在事务提交时出现了异常,事务在回滚后会继续抛出一个异常,虽然在我的程序中,事务抛出异常的概率较低,但是为了保险,我还是将我的业务方法的代码体用try...catch...块包了一层。请问有更好的处理方式吗?
一次问可能有点多,但是,对于比我聪明而又经验丰富的各位侠客来说就是小菜一碟了,谢谢了:)
问题补充:
补充:
对于第三点,那么,我如何捕获Spring事务抛出的异常呢?
问题补充:
谢谢各位的回复。
但是有点我不太明白,我没有看过Spring的事务的源代码,但是我认为的事务处理就是Spring环绕通知机制吧,效果应该相当于:
Java代码
try{
//开启事务
Transaction tx = session.beginTransactioin();
//回调我的service方法
myServiceMethod();
//提交事务
tx.commit();
catch(某范围的异常){
//Spring对异常的一些自定义处理。
... ...
}
try{
//开启事务
Transaction tx = session.beginTransactioin();
//回调我的service方法
myServiceMethod();
//提交事务
tx.commit();
catch(某范围的异常){
//Spring对异常的一些自定义处理。
... ...
}
因此——若我的理解是正确的话,在出现事务异常时,我的service方法myServiceMethod()是没法捕获事务的异常的,也就没法抛出我自定义的异常类。
表现层已经写好,由其他组维护,我不便改,而Action只捕获了公司的自定义异常及其子类异常,也就没法捕获Spring的DataAccessException。
请问还有什么好的处理方法吗?
1. 会。 spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行commit or rollback(取决于是否抛出runtime异常).
2.如果抛出runtime exception 并在你的业务方法中没有catch到的话,事务会回滚。
3.一般不需要在业务方法中catch异常,如果非要catch,在做完你想做的工作后(比如关闭文件等)一定要抛出runtime exception,否则spring会将你的操作commit,这样就会产生脏数据.所以你的catch代码是画蛇添足。
seagullgao (初级程序员) 2009-05-30
sping事务的exception一般在调用该service的action中catch,然后将结果导到出错页面,告诉user出差的原因。如果你想知道详细的出错原因,可以在spring的 service中抛出自定义exception,然后在出错页面中显示不同的出错message.
seagullgao (初级程序员) 2009-06-08
SPRING2.5中,HIBERNETTEMPLATE是线程和事务绑定的,这和spring2.0不一样,现在的数据库操作基类都是2.0的,在执行数据库变更操作时候会自动执行,然而在2.5中它不会,需要手动在绑定事务的hibernetTemplate上执行flush()