@Transactional适用于服务中的公共方法,但不适用于受保护的方法

时间:2018-05-18 09:09:09

标签: java hibernate spring-boot jpa transactional

我试图从同一服务impl类中的另一个服务方法(A)调用服务方法(B)。现在,当我把@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

我的类调用结构是这样的 Docs

A =失败案件
B =成功案例

doProcessS()==&gt;公共空白 doSubProcessS()==&gt;受保护的空白

我正在使用SpringBoot 2.0.0.RELEASE

我想执行A&#39; A&#39;方式而不是&#39; B&#39;因为我想根据doSubProcess()中提交给DB的数据执行另一个doProcessS()检查

1 个答案:

答案 0 :(得分:1)

@Transactional基于Spring AOP

Spring AOP在自调用方法中不起作用(在同一个类中)

您可以将doProcessS()中的ServiceImpl标记为@Transactional

来解决此问题

Reference

  

这意味着对该对象引用的方法调用将被调用   代理,因此代理将能够委托给所有人   与特定方法相关的拦截器(建议)   呼叫。但是,一旦调用终于到达目标对象,   在这种情况下,SimplePojo引用,任何方法都可以调用它   make on,例如this.bar()或this.foo(),将会是   针对此引用而不是代理调用。这有   重要的含义。这意味着自我调用不会发生   得到与方法调用相关的建议   有机会执行。

如果您要分离您的交易,请将doSubProcessS委托给其他类,并将其传播类型标记为Propagation.REQUIRES_NEW