Spring transaction failure reasons

1 The database engine does not support transactions

Spring transactions are business layer transactions, and their bottom layer still relies on the transaction support of the database itself. Taking MySQL as an example, its MyISAM engine does not support transaction operations. InnoDB is the engine that supports transactions. InnoDB is generally used to support transactions.

2 classes are not managed by Spring

As shown in the following example:

//@Service
public class OrderServiceImpl implements OrderService {
    
       
    @Transactional    
    public void updateOrder(Order order) {
    
            
        // 业务逻辑    
    }
}

If you comment out the annotation at this time @Service, this class will not be loaded into a Bean, then this class will not be Springmanaged, and the transaction will be invalid.

3 The method is not public

@TransactionalIt can only be used publicon methods, otherwise the transaction will not be invalidated. If you want to use it on non- publicmethods, you can turn on AspectJthe proxy mode.

4 Self-calling problem

Example 1:

@Service
public class OrderServiceImpl implements OrderService {
    
        
    public void update(Order order) {
    
            
        updateOrder(order);    
    }    
    @Transactional    
    public void updateOrder(Order order) {
    
            
        // 业务逻辑    
    }
}

updateThere are no annotations on the method @Transactional , call @Transactionalthe annotated updateOrdermethod, and updateOrderadd a transaction to the method.

Example 2:

@Service
public class OrderServiceImpl implements OrderService {
    
       
    @Transactional    
    public void update(Order order) {
    
           
        updateOrder(order);    
    }    
    @Transactional(propagation = Propagation.REQUIRES_NEW)    
    public void updateOrder(Order order) {
    
            
        // 业务逻辑    
    }
}

In Example 2 , updatethe method is added and a new transaction is opened.@TransactionalupdateOrderREQUIRES_NEW

In the above two examples, the transactions will not take effect because they are called by themselves, that is, calling the class's own method without going through Spring's proxy class. By default, the transaction will only take effect when called externally.

5 The data source does not have a transaction manager configured

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    
    
    return new DataSourceTransactionManager(dataSource);
}

As shown above, even if Spring's transaction management function is used in the code, if Spring's transaction manager is not configured in the project, Spring's transaction will not take effect.

6 Transactions are not supported

propagationTransaction propagation behavior misconfiguration
Example:

@Service
public class OrderServiceImpl implements OrderService {
    
        
    @Transactional    
    public void update(Order order) {
    
            
        updateOrder(order);    
    }    
    @Transactional(propagation = Propagation.NOT_SUPPORTED)    
    public void updateOrder(Order order) {
    
            
        // 业务逻辑   
    }
}

Propagation.NOT_SUPPORTED: Indicates that it will not run as a transaction, and if there is currently a transaction, it will be suspended.

If Propagation is configured not to support running in transaction mode, the transaction will not take effect.

7 Abnormal was eaten

Example:

@Service
public class OrderServiceImpl implements OrderService {
    
       
    @Transactional    
    public void updateOrder(Order order) {
    
            
        try {
    
                
            // 业务代码        
        } catch {
    
    
            
        }    
    }
}

If you eat the exception and then don't throw it out, the transaction will not be rolled back!

8 Exception type error

Example:

@Service
public class OrderServiceImpl implements OrderService {
    
       
    @Transactional    
    public void updateOrder(Order order) {
    
            
        try {
    
                
            // 业务代码        
        } catch {
    
                
            throw new Exception("更新错误");        
        }    
    }
}

This transaction will not take effect, because the default rollback is: RuntimeExceptionIf you want to trigger the rollback of other exceptions, you need to configure it on the annotation, such as:
@Transactional(rollbackFor = Exception.class)
This configuration is limited to the Throwable exception class and its subclasses.

9 The exception occurred in the newly created thread

@Service
public class UserService {
    
    
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleService roleService;
 
    @Transactional
    public void add(UserModel userModel) throws Exception {
    
    
        userMapper.insertUser(userModel);
        new Thread(() -> {
    
    
            // 此处发生异常
            roleService.save();
        }).start();
    }
}
@Service
public class RoleService {
    
    
    @Transactional
    public void save() {
    
    
        // 保存数据
    }
}

We can see that in the transaction method add, the transaction method save is called, but the transaction method save is called in another thread. This will result in the two methods not being in the same thread and obtaining different database connections, resulting in two different transactions. If an exception is thrown in the save method, it is impossible to roll back the add method.

Guess you like

Origin blog.csdn.net/qq_41943900/article/details/133386156