简体   繁体   English

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

[英]@Transactional works on public method in service but not with protected method

I am trying to call a service method(B) from another service method(A) from same service impl class. 我正在尝试从同一服务展示类中的另一个服务方法(A)调用服务方法(B)。 Now when I put @Transactional on #A, everything works fine, but when I put the same on #B everything breaks apart. 现在,当我将@Transactional放在#A上时,一切正常,但是当我将同样的内容放在#B上时,一切都破裂了。 And the error that I get is 我得到的错误是

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

My class call structure is like this 我的课堂通话结构是这样的 在此处输入图片说明

A = fail case A =失败案例
B = success case B =成功案例

doProcessS() ==> public void doProcessS()==>公共无效
doSubProcessS() ==> protected void doSubProcessS()==>受保护的void

I am using SpringBoot 2.0.0.RELEASE 我正在使用SpringBoot 2.0.0.RELEASE

I want to execute everything in 'A' way and not 'B' as I want to execute another check in doProcessS() based on data committed to DB in doSubProcess() 我想以“ A”方式而不是“ B”方式执行所有操作,因为我想基于提交给doSubProcess()中数据库的数据在doProcessS()中执行另一项检查

@Transactional is based on Spring AOP @Transactional基于Spring AOP

Spring AOP does not work in self-invocation method (Within the same class) Spring AOP在自调用方法中不起作用(在同一类中)

You can fix it by mark your doProcessS() in ServiceImpl as @Transactional 您可以通过在ServiceImpl doProcessS()标记为@Transactional来修复它

Reference 参考

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. 但是,一旦调用最终到达目标对象(在这种情况下为SimplePojo引用),它可能会对自身调用的任何方法调用(例如this.bar()或this.foo())都会被调用。此参考,而不是代理。 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. 这意味着自调用不会导致与方法调用相关的建议得到执行的机会。

If you want to separate your transaction, delegate doSubProcessS to other class and mark it propagation type as Propagation.REQUIRES_NEW 如果要分离事务, doSubProcessS委托给其他类,并将其传播类型标记为Propagation.REQUIRES_NEW

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM