zoukankan      html  css  js  c++  java
  • spring事务(Transaction )报 marked as rollback-only异常的原因及解决方法

    很多朋友在使用spring+hibernate或mybatis等框架时经常遇到报Transaction rolled back because it has been marked as rollback-only的异常,这个异常是怎么造成的

    呢,下面将给大家进行详细的分析。

        这是专门写的一个造成该异常的代码:

    @Transactional
        public void add(OperateLog entity)throws Exception {
            // TODO Auto-generated method stub
            operateLogDao.add(entity);
        }
    @Transactional
        public void save(Member member) throws Exception {
            memberDao.add(member);
        }
     
        @Transactional
        public void add(Member member) throws Exception {
            try {
                this.save(member);
                /*
                 * 日志的title长度为10 我把值设置为add111111111111111111是为了造成异常
                 */
                OperateLog entity = new OperateLog("add111111111111111111", "1111");
                operateLogService.add(entity);
            } catch (Exception e) {
                e.printStackTrace();
                // throw e;
            }
     
        }

    执行以上代码就会报改异常,当我把
    //throw e;的注释//去掉,当我执行后就不会有改异常,只会报标题title太长的异常。如下面提示:

    Caused by: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column '_title' at row 1
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4072)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4006)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2468)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2629)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2719)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2450)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2371)
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2355)
        at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
        at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
        at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:94)
        at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57)

    通过以上的问题我们可以发现。在spring中,在事务方法中调用多个事务方法时,spring将会把这些事务合二为一。当整个方法中每个子方法没报错时,整个方法执行完才提交事务(大家可以使用debug测试),如果某个子方法有异常,spring将该事务标志为rollback only。如果这个子方法没有将异常往上整个方法抛出或整个方法未往上抛出,那么改异常就不会触发事务进行回滚,事务就会在整个方法执行完后就会提交,这时就会造成Transaction rolled back because it has been marked as rollback-only的异常,就如上面代码中未抛throw e 一样。如果我们往上抛了改异常,spring就会获取异常,并执行回滚。

  • 相关阅读:
    《面试题 03.05. 栈排序》——惰性更新
    CTF<密码学> writeup 传统知识+古典密码
    有趣的数学(二)
    【】Dedecms友情链接去掉LI的方法介绍
    【】【】打工子弟学校学生们的中国梦何时圆?
    Discuz! 7.2 防注册机注册+发垃圾帖的解决方法
    Windows 8 常用快捷键
    Win7 64位系统下Auto CAD 2010注册激活,出现警告:Make sure you can write to current directory...
    怎么从EXCEL或WORD里提取图片?
    如何将windows xp系统下的outlook express6.0的邮件,帐号及通迅录导入Office Outlook xp/2003/2007中...
  • 原文地址:https://www.cnblogs.com/zhuyeshen/p/10913814.html
Copyright © 2011-2022 走看看