У меня есть проект Spring-boot, где у меня есть служебный компонент с 2 @Transactional
аннотированными методами.
Эти методы выполняют действия JPA (спящего режима) только для чтения, чтобы извлекать данные из файловой базы данных H SQL, используя как репозитории JPA, так и загрузчики с отложенной загрузкой в сущностях.
У меня также есть CliBan, который обрабатывает команды (используя PicoCLI). Из одной из этих команд я пытаюсь вызвать оба @Transactional
аннотированных методов, но я получаю следующую ошибку при выполнении второго метода:
org.hibernate.LazyInitializationException - could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:602)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:217)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:581)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:148)
at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:188)
at java.util.Spliterators$IteratorSpliterator.estimateSize(Spliterators.java:1821)
at java.util.Spliterator.getExactSizeIfKnown(Spliterator.java:408)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566)
at <mypackage>.SomeImpl.getThings(SomeImpl.java:<linenr>)
...
Если я отмечу метод, который вызывает оба @Transactional
аннотированных методы с самим @Transactional
, код, кажется, работает (так как теперь я предполагаю, что это только 1 транзакция верхнего уровня?).
Я просто хочу выяснить, почему я не могу запустить несколько транзакций в одном сеансе или почему вторая транзакция не запускает новый сеанс, если его нет.
Итак, мои вопросы:
- Это связано с тем, как hibernate запускает сеанс, как транзакции закрывают сеансы или что-либо, связанное с базой данных H SQL?
- Является ли добавление включающей транзакции правильным способом решения проблемы или это просто устранение симптома?
- Как лучше всего использовать несколько
@Transactional
аннотированных методов из одного метода?
РЕДАКТИРОВАТЬ: Я хочу пояснить, что я не выставляю сущности вне транзакционных методов, так что на первый взгляд мне кажется, что 2 транзакционных метода должны работать независимо друг от друга.
EDIT2: для большей ясности: транзакционные методы должны быть доступны в API. и пользователь API должен иметь возможность вызывать несколько из этих транзакционных методов, без необходимости использовать транзакционные аннотации и без получения LazyInitializationException
Api:
public interface SomeApi {
List<String> getSomeList();
List<Something> getThings(String somethingGroupName);
}
Реализация:
public class SomeImpl implements SomeApi {
@Transactional
public List<String> getSomeList() {
return ...; //Do jpa stuff to get the list
}
@Transactional
public List<Something> getThings(String somethingGroupName) {
return ...; //Do other jpa stuff to get the result from the group name
}
}
Использование третьей стороной (которая может не знать, что такое транзакционность):
public someMethod(String somethingGroupName) {
...
SomeApi someApi = ...; // Get an implementation of the api in some way
List<String> someList = someApi.someList();
if (someList.contains(somethingGroupName) {
System.out.println(someApi.getThings(somethingGroupName));
}
...
}