1. 程式人生 > 其它 >@Transactional失效的場景及解決

@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關鍵字來實現的,沒有經過動態代理物件,所以事務回滾失效。

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(rollbackFor=Exception.class)

解決辦法二: @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;