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就会获取异常,并执行回滚。

  • 相关阅读:
    发送邮件以及数据导出
    GridView的使用(高度封装,不怎么灵活,repeat可替代)
    索引学习(一)
    JVM 学习笔记(二)
    JVM 学习笔记(一)
    JDBC 基础知识总结
    需要学习的点
    The Unified Modeling Language(UML)
    向往2的年代
    SQL 各种连接:内连接,外连接(左外,右外,完全外)
  • 原文地址:https://www.cnblogs.com/zhuyeshen/p/10913814.html
Copyright © 2011-2022 走看看