• @Transactional失效的场景及解决


    1.@Transactional修饰的方法为非public方法,这个时候@Transactional会实现。
    失败的原理是:@Transactional是基于动态代理来实现的,非public的方法,他@Transactional的动态代理对象信息为空,所以不能回滚。

    2.在类内部没有添加@Transactional的方法,调用了@Transactional方法时,当你调用是,他也不会回滚
    测试代码如下:

    @Service
    public class UserServiceImpl extends  implements UserService {
    
        @Autowired
        private UserMapper userMapper;
    
        @Override
        @Transactional
        public void insertOne() {
            User user = new User();
            user.setUsername("123");
            //插入到数据库
            userMapper.insert(user);
            //手动抛出异常
            throw new IndexOutOfBoundsException();
        } 
    }

    失败的原理:@Transactional是基于动态代理对象来实现的,而在类内部的方法的调用是通过this关键字来实现的,没有经过动态代理对象,所以事务回滚失效。

    Spring框架的事务处理代码默认地只在抛出运行时和unchecked exceptions时才标识事务回滚。 也就是说,当抛出个RuntimeException 或其子类的实例时,(Errors 也一样 - 默认地 - 标识事务回滚。)

    从事务方法中抛出的Checked exceptions将不被标识进行事务回滚。

    解决办法:

    在@Transactional中加上(rollbackFor = Exception.class) ==》@Transactional(rollbackFor = Exception.class)

    3.就是在@Transactional方法内部捕获了异常,没有在catch代码块里面重新抛出异常,事务也不会回滚。

    测试代码如下:

        @Override
        @Transactional
        public void insertOne() {
            try {
                User user = new User();
                user.setUsername("123");
                //插入到数据库
                userMapper.insert(user);
                //手动抛出异常
                throw new IndexOutOfBoundsException();
            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
        }

    解决办法@Transactional的方法里面捕获了异常,手动回滚,
    代码如下:

    @Override
        @Transactional
        public void insertOne() {
            try {
                User user = new User();
                user.setUsername("123");
                //插入到数据库
                userMapper.insert(userEntity);
                //手动抛出异常
                throw new IndexOutOfBoundsException();
            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }
        }

    4.创建表时,引擎是否是InnerDB

    mysql数据库常用的引擎有两种(innodb和myisam),在建表时有些dba会默认使用myisam引擎,如果是这种引擎,那么在遇到异常时,数据库是不回滚的。所以将需要回滚的表引擎改为innodb

    解决方法:

    ALTER TABLE tableName CHANGE TYPE=InnoDB;
  • 相关阅读:
    IDEA 2017 安装和破解
    Linux新增开放端口
    ping指定IP的指定端口号
    Ubuntu防火墙常用命令
    Ubuntu端口常用命令
    File Zilla连接Ubuntu 失败
    Docker常用命令详解
    Linux的vi常用命令详解
    Qt事件系统之二:鼠标事件和滚轮事件
    Qt事件系统之一:Qt中的事件处理与传递
  • 原文地址:https://www.cnblogs.com/mylqm/p/14926129.html
Copyright © 2020-2023  润新知