Example of @transactional internal call 🌰

Under Spring’s AOP proxy, target methods are managed by spring-generated proxy objects only if they are called externally, which can cause self-invocation problems. If another method in the same class that does not have the @Transactional annotation calls the @Transactional annotation method internally, the transaction for the @Transactional annotation method is ignored and does not roll back


@Service
public class A{
    
    public void action(a){
        dosome();
    }
    
    @Transactional
    public void dosome(a){
        doa.insert(newObject()); }}Copy the code

As shown above, when an exception is thrown in method dosome(), the data operation is not rolled back

The solution

Idea: Force the use of AspectJ for method profiling

Springboot introduces AspectJ facets

Add AspectJ to POM.xml:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<! -- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.5</version>
</dependency>
Copy the code
Add @enableAspectJAutoProxy to the startup class (exposeProxy = true)
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)
public class DonngPartsApplication {

	public static void main(String[] args) { SpringApplication.run(DonngPartsApplication.class, args); }}Copy the code

Note: exposeProxy = true if not added, will report:

java.lang.IllegalStateException:

Cannot find current proxy: Set ‘exposeProxy’ property on Advised to ‘true’ to make it available,

and ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.

(A) aopContext.currentProxy ().dosome()

Change to the following code and the transaction takes effect

@Service
public class A{
    
    public void action(a){
        ((A) AopContext.currentProxy()).dosome();
    }
    
    @Transactional
    public void dosome(a){
        doa.insert(newObject()); }}Copy the code

@ Transactional advanced

1. Attribute information for the @Transactional annotation

attribute describe
name When you have multiple transactionmanagers in a configuration file, you can use this property to specify which TransactionManager to select
propagation The propagation behavior of the transaction, which defaults to REQUIRED
isolation The isolation degree of a transaction is DEFAULT
timeout Timeout period for a transaction. Default value is -1. If the time limit is exceeded but the transaction has not completed, the transaction is automatically rolled back
read-only Specifies whether the transaction is read-only. The default value is false. To ignore methods that do not require transactions, such as reading data, you can set read-only to true
rollback-for Specifies the type of exception that can trigger transaction rollback. If more than one exception type needs to be specified, separate the exception types by commas
no-rollback- for Throw the exception type specified by no-rollback-for without rolling back the transaction

2. Propagation

  • REQUIRED: Join a transaction if one exists, create a new one if not (default)
  • NOT_SUPPORTED: The container does not enable transactions for this method
  • REQUIRES_NEW: A new transaction is created regardless of whether a transaction exists, the old one is suspended, the new one is executed, and the old one continues
  • MANDATORY: Must be executed in an existing transaction, or an exception is thrown
  • NEVER: must be executed in a transaction that does not exist, otherwise an exception is thrown (as opposed to MANDATORY)
  • SUPPORTS: Transactions are used if other beans call this method and declare transactions in other beans. If the other bean does not declare a transaction, then no transaction is required.
  • NESTED: If a transaction currently exists, it is executed within a NESTED transaction. If there are no transactions currently, an operation similar to PROPAGATION_REQUIRED is performed.

3. Transaction timeout setting

Transactional(timeout=30) // The default is 30 seconds

4. Transaction isolation level Isolation

  • READ_UNCOMMITTED: Reads uncommitted data (dirty reads and unrepeatable reads occur)
  • READ_COMMITTED: Reads committed data (unrepeatable reads and phantom reads occur)
  • REPEATABLE_READ: repeatable reading (phantom reading can occur)
  • SERIALIZABLE: serialization

Pay attention to

Transactional can only be applied to public methods

The mere presence of the @Transactional annotation does not enable Transactional behavior; it is simply metadata

Call it a day!!!!!!

For more interesting and interesting content, welcome to my blog to communicate and improve WaterMin together