Case 2 Spring transaction failure

Use the default transaction mode

  Because of the design of java, it is not considered inherited RuntimeException exception is "checkException" or common abnormalities, such as IOException, these exceptions in java syntax is mandatory process. For these common abnormalities, spring they have been processed by default, so the default is not rolled back. You can add rollbackfor = Exception.class to represent all Exception are rolled back.

Internal call

  Method without a transaction call methods in the class with the transaction will not be rolled back. Spring is used because the rollback generated proxy mode, if the method is a method without a transaction with a transaction such calls directly through the this.xxx()call without generating agent transaction, so the transaction does not work. Common solution, the dissolution of class.

  spring call in a transaction process A has another pending transaction and will create a new transaction Method B, if you use this to call this method B, 
this time Method B dished out a game, this time Method B the transaction will fail. And will not be rolled back. 

  • PROPAGATION_REQUIRED: If there is a transaction, the current transaction support. If no transaction is open Transaction;
  • PROPAGATION_REQUIRES_NEW: Always start a new business. If a transaction already exists, the existing transaction pending.

as follows:

@Service
 public  class the EmployeeService { 
 
    @Autowired 
    Private EmployeeDao EmployeeDao; 
 
    public  void Save () {
         the try {        
             this .saveEmployee ();   // where this call does not turn on the transaction, the data is saved 
        } the catch (Exception E) { 
            E. printStackTrace (); 
        } 
    } 
    
    @Transactional (propagation = Propagation.PROPAGATION_REQUIRED)
     // here whether or PROPAGATION_REQUIRED PROPAGATION_REQUIRES_NEW, transaction take effect not 
    public  void saveEmployee () { 
        the Employee Employee= new Employee();
        employee.setName("zhangsan");
        employee.setAge("26";
        employeeDao.save(employee);
        throw new RuntimeException();
    }
}

问题原因:

JDK dynamic proxy. Only when the transaction will generate a dynamic proxy called directly. Object calls returned in SpringIoC container is a proxy object instead of a real object. And this here is EmployeeServicethe real object rather than the proxy object.

解决办法:

CLAIMS 1. A method for the open transaction in process B without default transaction or a transaction, and catch Method A throw new RuntimeException();(rollbackFor when not specified, the default rollback abnormality RuntimeException), such use is the method A transaction. (Must throw new RuntimeException();otherwise exception is the capture process, the same will not be rolled back.) As follows:

@Transactional () // turn transaction 
public  void Save () {
     the try {        
         this .saveEmployee ();   // where this call transaction will fail, data will be saved 
    } the catch (Exception E) { 
        e.printStackTrace (); 
        the throw  new new a RuntimeException (); 
    } 
}

Method 2, Method A may not turn on the transaction, the transaction opening procedure B, A and this will call into a dynamic method call agent ( AopContext.currentProxy()), as follows:

public void save(){
    try {        
        EmployeeService proxy =(EmployeeService) AopContext.currentProxy();
        proxy.saveEmployee();
    }catch (Exception e){
        e.printStackTrace();
    }
}

 

 

Reference: two cases of failure of the transaction spring

Reference: the Spring used to call this the reason the transaction failed

Reference: One reason Spring's transaction failure (this call)

Guess you like

Origin www.cnblogs.com/heqiyoujing/p/11221093.html