@Transactional работает с публичным методом в сервисе, но не защищенным методом - PullRequest
0 голосов
/ 18 мая 2018

Я пытаюсь вызвать сервисный метод (B) из другого сервисного метода (A) из того же класса обслуживания impl.Теперь, когда я помещаю @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

Моя структура вызова класса выглядит следующим образом enter image description here

A = неудачный случай
B = успешный случай

doProcessS () ==> public void
doSubProcessS () ==> protected void

Я использую SpringBoot 2.0.0.RELEASE

Я хочу выполнить всеспособом 'A', а не 'B', поскольку я хочу выполнить еще одну проверку в doProcessS () на основе данных, переданных в БД в doSubProcess ()

1 Ответ

0 голосов
/ 18 мая 2018

@Transactional основан на Spring AOP

Spring AOP не работает в методе самовывоза (в том же классе)

Вы можете исправить это, отметив свой doProcessS()в ServiceImpl как @Transactional

Ссылка

Это означает, что вызовы метода для этой ссылки на объект будут вызовами на прокси-сервере, и поэтомупрокси сможет делегировать всем перехватчикам (рекомендации), которые имеют отношение к этому конкретному вызову метода.Однако, как только вызов, наконец, достигнет целевого объекта, в этом случае ссылка SimplePojo, любые вызовы методов, которые он может сделать сам, такие как this.bar () или this.foo (), будут вызываться противэто ссылка, а не прокси.Это имеет важные последствия.Это означает, что самовывоз не приведет к тому, что совет, связанный с вызовом метода, получит шанс на выполнение.

Если вы хотите отделить транзакцию, делегируйте doSubProcessS другому классу ипометить тип распространения как Propagation.REQUIRES_NEW

...