我有一个奇怪的问题:
假设我有两个实体类,例如Container
和ContainedObject
。 Container
与@OneToMany
的关系ContainedObject
。
直接获取包含的对象时,一切正常,但是当从后台线程运行时,我得到“无法初始化代理 - 没有会话”。
示例:
@Component
public class Something {
@Autowired
private ContainerRepository _repo;
public void doInForeground() {
Container container = _repo.findOne(42L); // suppose 42 exists
container.getContainedObjects().size(); // succeeds
}
public void submitToBackground() {
CompletableFuture<Void> f = CompletableFuture.supplyAsync(() -> doInBackground());
}
private Void doInBackground() {
Container container = _repo.findOne(42L);
container.getContainedObjects().size(); // throws LazyInitializationException
}
}
ContainerRepository
是PagingAndSortingRepository
。运行doInForeground
成功,但submitToBackground
会抛出众所周知的LazyInitializationException
“无法初始化代理 - 无会话”
好像没有启动任何交易或者关闭太快。使用@Transactional
注释任何方法都无济于事。
是否根本无法在后台线程中使用Spring-JPA,还是需要额外的魔法?
答案 0 :(得分:0)
1)您需要readOnly事务来获取延迟集合。
2)我认为@Transactional不适用于本地方法,因为当你调用本地方法时,你直接调用实现,而不是Spring创建的代理对象。
如果是这种情况,至少有两种选择:
1)切换到Aspectj
<tx:annotation-driven mode="aspectj" proxy-target-class="true"/>
2)使用doInForeground()
内的TransactionTemplate手动创建交易:
http://simplespringtutorial.com/springProgrammaticTransactions.html