java 事务不能回滚问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 事务不能回滚问题相关的知识,希望对你有一定的参考价值。

public static void test()
String sql = "update t_test set name = 5 where id = 5";
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try
conn = DBUtil.getConn();
conn.setAutoCommit(false);

ps = conn.prepareStatement(sql);
ps.executeUpdate();
conn.commit();
if(true)//故意出现Exception
throw new SQLException("wrong");


catch (SQLException e)
try
conn.rollback();//出现了异常,不会回滚!
catch (SQLException e1)
e1.printStackTrace();

throw new DaoException(e.getMessage(),e);
finally
DBUtil.close(rs, ps, conn);


为何事务不会回滚?回滚有什么要求?是不是回滚一定要放在catch的Exception里?
我用的是mysql,表类型也是InnoDB的,

原因很简单,你在throw这个SQL Exception之前已经把事务commit掉了,你这个conn.commit()应该是try块的最后一句语句。 回滚是针对没有提交的事务的。 参考技术A 把提交语句conn.commit();放到if(true)throw new.....的后面。事物已经提交,当然无法回滚了。 参考技术B 你这个打印出异常错误没有?如果有 无视下面一段话

我自己猜想啊 这个try捕获的是执行异常
就是发生在数据库中的异常
而你自己抛出的这个异常时另外一个异常
你试一下把new给去掉
你这个代码如果出现异常一定是会回滚的
参考技术C 你都提交了,然后才出现错误,当然不回滚了。你将异常放到commit前面。 参考技术D 是的。

Service中事务不能回滚的解决方式(转)

1、在service方法里面如果对异常进行了捕获的话,该事务是不会进行回滚的 
       默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚。   
       spring aop  异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeexception的异常,但可以通过配置来捕获特定的异常并回滚,换句话说在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被aop捕获进而回滚 
  解决方案:  
  方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在controller层要继续捕获这个异常并处理 

  方案2.在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常(现在项目的做法)

 

在service中try。。。catch,在catch块中抛出runtimeException无法实现回滚,不知道为什么。

现在的解决时方案2.或者controller回滚。

以上是关于java 事务不能回滚问题的主要内容,如果未能解决你的问题,请参考以下文章

Java事务不回滚的原因总结

ROLLBACK语句只能针对未提交的事务进行回滚操作,已提交的事务是不能回滚的?

oracle 提交事务后为啥不能撤销或回滚,不是有撤销段吗

spring自己抛出异常,居然不能回滚

事务教程——测试回滚

MYSQL事务与锁表的问题?