1. The method isnon-publicmodified

Let’s look at the database

The reason for this depends on the Transactional source code, which verifies that it is public. Otherwise, @Transactional will not parse at all.

A method call in the same class causes @Transactional to fail(Common pit)

  • SaveA does not have a transaction annotation, saveA2 has a transaction annotation, saveA call saveA2 using this, saveA2 transaction annotation will be invalid

The reason: Spring automatically generates a proxy class for a class annotated with the @Transactional annotation when scanning beans. When an annotated method is called, it is actually called by the proxy class. The proxy class starts a transaction before invoking it, but methods in the class call each other. Equivalent to this.savea2 (), the saveA2 method is not called by the proxy class, but directly from the original Bean, so the annotations will be invalid

Note that even if this is not shown, this is called after compilation (this is not present in uncompiled code), as shown below

Take a look at the phenomenon:

Database:

Mine? Is the saveA2 transaction not in effect? Ha ha

But what if I just need to call it in class and want it to work?

Use ((TransactionalInvalidationImpl) AopContext. CurrentProxy ()). SaveA2 ();

If the above code starts after… I went to report the error:

java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.

	at org.springframework.aop.framework.AopContext.currentProxy(AopContext.java:69)
	at com.xzll.test.service.impl.TransactionalInvalidationImpl.saveA(TransactionalInvalidationImpl.java:31)
	at com.xzll.test.service.impl.TransactionalInvalidationImpl$$FastClassBySpringCGLIB$$8c5749ef.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684)
	at com.xzll.test.service.impl.TransactionalInvalidationImpl$$EnhancerBySpringCGLIB$$b4a8c905.saveA(<generated>)
	at com.xzll.test.transactional.TransactionalInvalidationTest.test(TransactionalInvalidationTest.java:25)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallba cks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallback s.java:84) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.ja va:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java :86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java :61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Copy the code
  • Solution:Add @enableAspectJAutoProxy (exposeProxy = true)//exposeProxy literally exposes proxy

If you look at the database, you can see that saveA2 is not saved successfully, only saveA is saved successfully. You know that the saveA2 transaction is in effect.

  • Another workaround (essentially the same as EnableAspectJAutoProxy) is to modify the bean definition information to be the implementationBeanDefinitionRegistryPostProcessor

(For the record, @enableAspectJAutoProxy (exposeProxy = true) does this internally lol)

Notice that we’ve commented out @enableAspectJAutoProxy at this point.

You can see that the transaction takes effect and the saveA2 data is not saved but rolled back.


  • Note that if the caller uses a transaction, the transaction will work even if the same method is called with this. Instead of saveA2, saveA will work

Take a look at the phenomenon:

As shown, the transaction is rolled back and the data is not inserted

3. Transaction parameters are incorrectly set

Such as:

  • Propagation Propagation levels For details, see juejin.cn/post/700807…
  • RollbackFor Rollback condition

I won’t show you how catch can also cause failure.

In addition, recommend a more in-depth article stamp here from the source level