The reason for the failure of spring transaction (invoking your own reason solution)

1. The database engine does not support transactions
. Take MySQL as an example. Its MyISAM engine does not support transaction operations. InnoDB is the engine that supports transactions. Generally, InnoDB is used to support transactions.
2. It is not managed by Spring.

// @Service
public class OrderServiceImpl implements OrderService {
    
    

    @Transactional
    public void updateOrder(Order order) {
    
    
        // update order
    }
}

If the
@Service annotation is commented out at this time , this class will not be loaded as a Bean, then this class will not be managed by Spring, and the transaction will naturally become invalid.
3. The method is not public, which
probably means that
@Transactional can only It is used for public methods, otherwise the transaction will not fail. If you want to use it for non-public methods, you can enable
AspectJ proxy mode.
4. Self-calling problem
Let's look at two examples:

@Service
public class OrderServiceImpl implements OrderService {
    
    

    public void update(Order order) {
    
    
        updateOrder(order);
    }

    @Transactional
    public void updateOrder(Order order) {
    
    
        // update order
    }

}

There is no @Transactional annotation on the update method, and the updateOrder method with @Transactional annotation is called. Does the transaction on the updateOrder method work?
Let's look at the following example again:

@Service
public class OrderServiceImpl implements OrderService {
    
    

    @Transactional
    public void update(Order order) {
    
    
        updateOrder(order);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateOrder(Order order) {
    
    
        // update order
    }

}

This time, @Transactional is added to the update method, and REQUIRES_NEW is added to updateOrder to start a new transaction. Will the newly opened transaction work?
The answer to these two examples is: it doesn't work!
Because they call their own methods, they call their own methods instead of Spring's proxy classes. By default, the transaction will only take effect when the transaction is called externally. This is also a classic problem that is often talked about.
Solution:

@Resource
private UpdateOrder updateOrder;
 public void update(Order order) {
    
    
        updateOrder.updateOrder(order);
    }

This is the same as spring @Sync requires proxy generation

https://www.cnblogs.com/jtlgb/p/11124770.html

5. The data source does not have a transaction manager configured

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

6, does not support affairs

@Transactional(propagation = Propagation.NOT_SUPPORTED)

7. If the exception is eaten,
try catch does not throw an exception. If the exception is eaten and then not thrown, how can the transaction be rolled back!
8. The exception type is wrong

 @Transactional
  public void updateOrder(Order order) 

This transaction is also not effective, because the default rollback is: RuntimeException, if 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.

Reference: https://zhuanlan.zhihu.com/p/101396825

Guess you like

Origin blog.csdn.net/qq_38893133/article/details/110819461