@Transactional 适用于服务中的 public 方法,但不适用于受保护的方法
@Transactional works on public method in service but not with protected method
我正在尝试从同一服务实现中的另一个服务方法 (A) 调用服务方法 (B) class。现在,当我将@Transactional 放在#A 上时,一切正常,但是当我将它放在#B 上时,一切都崩溃了。我得到的错误是
Exception: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: MyEntity.childs, could not initialize proxy - no Session
at <reference to my code>
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at <reference to my code>
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_162]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_162]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_162]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_162]
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:223) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.cloud.context.scope.GenericScope$LockedScopedProxyFactoryBean.invoke(GenericScope.java:483) ~[spring-cloud-context-2.0.0.RC1.jar:2.0.0.RC1]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at <reference to my code>
at <reference to my code>
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590) ~[na:1.8.0_162]
at <reference to my code>
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: MyEntity.childs, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:201) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:561) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:132) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:277) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at <reference to my code>
... 24 common frames omitted
我的class调用结构是这样的
A = 失败案例
B = 成功案例
doProcessS() ==> public void
doSubProcessS() ==> protected void
我正在使用 SpringBoot 2.0.0.RELEASE
我想以 'A' 方式而不是 'B' 执行所有操作,因为我想根据在 doSubProcess()
中提交给数据库的数据在 doProcessS() 中执行另一次检查
@Transactional
基于 Spring AOP
Spring AOP 在自调用方法中不起作用(同一个class)
您可以通过将 ServiceImpl
中的 doProcessS()
标记为 @Transactional
来修复它
This means that method calls on that object reference will be calls on
the proxy, and as such the proxy will be able to delegate to all of
the interceptors (advice) that are relevant to that particular method
call. However, once the call has finally reached the target object,
the SimplePojo reference in this case, any method calls that it may
make on itself, such as this.bar() or this.foo(), are going to be
invoked against the this reference, and not the proxy. This has
important implications. It means that self-invocation is not going to
result in the advice associated with a method invocation getting a
chance to execute.
如果您想分离您的交易,请将doSubProcessS
委托给其他class并将其传播类型标记为Propagation.REQUIRES_NEW
我正在尝试从同一服务实现中的另一个服务方法 (A) 调用服务方法 (B) class。现在,当我将@Transactional 放在#A 上时,一切正常,但是当我将它放在#B 上时,一切都崩溃了。我得到的错误是
Exception: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: MyEntity.childs, could not initialize proxy - no Session
at <reference to my code>
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at <reference to my code>
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_162]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_162]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_162]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_162]
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:223) ~[spring-core-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.cloud.context.scope.GenericScope$LockedScopedProxyFactoryBean.invoke(GenericScope.java:483) ~[spring-cloud-context-2.0.0.RC1.jar:2.0.0.RC1]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) ~[spring-aop-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at <reference to my code>
at <reference to my code>
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590) ~[na:1.8.0_162]
at <reference to my code>
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: MyEntity.childs, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:201) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:561) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:132) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:277) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at <reference to my code>
... 24 common frames omitted
我的class调用结构是这样的
A = 失败案例
B = 成功案例
doProcessS() ==> public void
doSubProcessS() ==> protected void
我正在使用 SpringBoot 2.0.0.RELEASE
我想以 'A' 方式而不是 'B' 执行所有操作,因为我想根据在 doSubProcess()
中提交给数据库的数据在 doProcessS() 中执行另一次检查@Transactional
基于 Spring AOP
Spring AOP 在自调用方法中不起作用(同一个class)
您可以通过将 ServiceImpl
中的 doProcessS()
标记为 @Transactional
This means that method calls on that object reference will be calls on the proxy, and as such the proxy will be able to delegate to all of the interceptors (advice) that are relevant to that particular method call. However, once the call has finally reached the target object, the SimplePojo reference in this case, any method calls that it may make on itself, such as this.bar() or this.foo(), are going to be invoked against the this reference, and not the proxy. This has important implications. It means that self-invocation is not going to result in the advice associated with a method invocation getting a chance to execute.
如果您想分离您的交易,请将doSubProcessS
委托给其他class并将其传播类型标记为Propagation.REQUIRES_NEW