Spring transaction failure

  

  • Isolation Levels

  In TransactionDefinition.java interface, it defines the " four kinds " isolation level enumeration:

/**
 * [Spring] exclusive use back-end database default isolation level
 *
 * REPEATABLE_READ isolation level used by default MySQL
 * READ_COMMITTED isolation level Oracle defaults
 */
int ISOLATION_DEFAULT = -1;

/**
 * Minimum isolation level, allowing the read data changes have not been submitted, may cause dirty reads, non-repeatable reads or phantom reads
 */
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;

/**
 * Allow concurrent transactions to read data already submitted, can prevent dirty reads, but phantom reads or non-repeatable read may still occur
 */
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
/**
 * Repeatedly read the results of the same field are the same, unless the data is modified their affairs themselves, can prevent dirty reads and non-repeatable reads, but phantom reads still occur.
 */
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
/**
 * Highest level of isolation, full compliance ACID isolation levels. All transactions executed one by one in sequence, it is impossible to produce interference between such matters, that is to say, this level prevents dirty reads, non-repeatable reads and phantom reads.
 *
 * But this will seriously affect the performance of the program. Under normal circumstances you do not need this level.
 */
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;

  

  

  • Spread level of the transaction

  Transaction propagation behavior , refers to the method of the current transaction configuration with the need to deal with how matters; for example: the method may continue to operate the existing transaction, or it may open a new transaction and run their own affairs;

  Note that spread level of the transaction, not the database transaction specification of the term, but as defined by Spring itself . Through the dissemination level of the transaction, Spring know how to handle transactions, it is to create a new transaction, or whether to continue using the current transaction;

 

  In TransactionDefinition.java interface defines three categories of seven kinds of spread levels:

// case ========== ========== support the current transaction 

/**
 * If the current transaction exists, use the transaction.
 * If there is no transaction, create a new business.
 */
int PROPAGATION_REQUIRED = 0;
/**
 * If the current transaction exists, use the transaction.
 * If no transactions, non-transactional way places continue to run.
 */
int PROPAGATION_SUPPORTS = 1;
/**
 * If the current transaction exists, use the transaction.
 * If there is no transaction, an exception is thrown.
 */
int PROPAGATION_MANDATORY = 2;

// case ========== ========== does not support the current transaction 

/**
 * Create a new business.
 * If the current transaction exists, put the current transaction pending.
 */
int PROPAGATION_REQUIRES_NEW = 3;
/**
 * Run in a non-transactional way.
 * If the current transaction exists, put the current transaction pending.
 */
int PROPAGATION_NOT_SUPPORTED = 4;
/**
 * Run in a non-transactional way.
 * If the current transaction exists, an exception is thrown.
 */
int PROPAGATION_NEVER = 5;

// ========== ========== other cases 

/**
 * If the current transaction exists, create a transaction as the current transaction nested transaction to run.
 * If no transaction, this is equivalent to {@link TransactionDefinition # PROPAGATION_REQUIRED}
 */
int PROPAGATION_NESTED = 6;

  

 

  • @Transaction

  Spring @Transaction tx of annotation module is provided, transaction control using AOP to achieve, i.e., the bottom of a dynamic proxy;

  @Transaction may act on the interface, the interface methods, classes, and class methods; when used as a class, the class of all public methods will have this type of transaction attributes, may be used in the method of labeling the class level to cover level Definition;

  

  Transaction failure

  1. Exception type Error, the default is RuntimException will be rolled back

  2. The exception was not thrown after the catch, throw an exception needs to be rolled back

  3. The question whether their call occurred

  4. notes whether the position where the public is modified

  The data source is not configured transaction manager

  6. The engine does not support transactions, such as MyIsam

 

  Here is an example of a failure of the transaction

@ Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;

    @Transactional
    @Override
    public void parent() {
        try {
            this.child();

        } catch (Exception e) {
            log.error ( "Insert abnormal", e);
        }


        Order order = new Order();
        order.setOrderNo("parent");
        order.setStatus("0");
        order.setTitle("parent");
        order.setAmount("1000");
        orderMapper.insert(order);
    }


    @Transactional
    @Override
    public void child() {

        Order order = new Order();
        order.setOrderNo("child");
        order.setStatus("0");
        order.setTitle("child");
        order.setAmount("2000");
        orderMapper.insert(order);

        throw new RuntimeException();
    }
}

  When calling parent process calls the child method, but is recorded after the execution of two complete insertion, it is a parent and a child is in;

  

  This is because the child above methods parent method call problems, @ Transaction is based AOP approach to transaction control (CglibAopProxy.java method interception, TransactionInterceptor.java proxy object calls the execution method), requires the use of a proxy object call method using the above code or the this, i.e. current instance of the object, thus performs this.child (), enhanced method can not be intercepted;

 

  The above method is modified as follows parent

    @Autowired
    private ApplicationContext context;

    private OrderService orderService;

    @PostConstruct
    public void init() {
        orderService = context.getBean(OrderService.class);
    }


    @Transactional
    @Override
    public void parent() {
        try {
            // Get the proxy object, call the child through a proxy object ()
            orderService.child();

       // Get a proxy object
            //OrderService orderService = (OrderService) AopContext.currentProxy();
            //orderService.child();
        } catch (Exception e) {
            log.error ( "Insert abnormal", e);
        }


        Order order = new Order();
        order.setOrderNo("parent");
        order.setStatus("0");
        order.setTitle("parent");
        order.setAmount("1000");
        orderMapper.insert(order);
    }

  

   Parent execution method, when there is an exception, the transaction will be rolled back;

 

 

   If you want to achieve when the parent method call, method call exception occurs child, child rollback only method for inserting the data, parent data insertion method is not rolled back, modified as follows

@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void child() {

	Order order = new Order();
	order.setOrderNo("child");
	order.setStatus("0");
	order.setTitle("child");
	order.setAmount("2000");
	orderMapper.insert(order);

	throw new RuntimeException();
}

    

 @Transactional(propagation = Propagation.REQUIRES_NEW)
 If the current transaction exists, the pending transaction and start a new transaction execution, after the new transaction is finished, pending transactions before the wake, continue; if the transaction does not currently exist, create a new transaction;

Guess you like

Origin www.cnblogs.com/coder-zyc/p/12181688.html