Multithreading 获取LazyInitializationException“;无法初始化代理-无会话“;在后台线程中运行事务时
我有一个奇怪的问题: 假设我有两个实体类,例如Multithreading 获取LazyInitializationException“;无法初始化代理-无会话“;在后台线程中运行事务时,multithreading,spring,hibernate,jpa,Multithreading,Spring,Hibernate,Jpa,我有一个奇怪的问题: 假设我有两个实体类,例如Container和ContainedObject容器与容器对象有@OneToMany关系 直接获取包含的对象时,一切正常,但从后台线程运行时,我得到“无法初始化代理-无会话” 例如: @Component public class Something { @Autowired private ContainerRepository _repo; public void doInForeground() {
Container
和ContainedObject
<代码>容器与容器对象
有@OneToMany
关系
直接获取包含的对象时,一切正常,但从后台线程运行时,我得到“无法初始化代理-无会话”
例如:
@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
}
}
@组件
公开课{
@自动连线
私人集装箱回购;
公共无效doinfo重磨(){
Container Container=_repo.findOne(42L);//假设42存在
container.getContainedObjects().size();//成功
}
公开作废提交背景(){
CompletableFuture f=CompletableFuture.supplyAsync(()->doInBackground());
}
私有Void doInBackground(){
容器容器=_repo.findOne(42L);
container.getContainedObjects().size();//引发LazyInitializationException
}
}
ContainerRepository
是一个分页和排序存储库
。运行doinfo重组
成功,但submitToBackground
抛出众所周知的LazyInitializationException
“无法初始化代理-无会话”
似乎没有启动任何事务或事务关闭过快。用@Transactional
注释任何方法也没有帮助
难道不能在后台线程中使用Spring JPA,或者需要任何额外的魔法吗?1)您需要一个只读事务来获取惰性集合
2) 我认为@Transactional不适用于本地方法,因为当您调用本地方法时,您直接调用实现,而不是Spring创建的代理对象
如果是这种情况,至少有两种选择:
1) 切换到Aspectj
<tx:annotation-driven mode="aspectj" proxy-target-class="true"/>
2) 在doinfo重组()中使用TransactionTemplate手动创建事务:
3。选择是将执行方法推送到另一个类中,以便代理可以工作。@Martin Frey是的,也是这样。Thanks@Martin弗雷:你说“推到另一个班”是什么意思?将另一个类自动关联到我的“某物”中,并将方法放在那里?/多同步:如何用Java编写上面的AspectJ XML片段?我将完全由注释驱动,没有任何XML。@rabejens关于另一个类-是的,您可以创建另一个类,并将事务注释方法放在那里。切换到Aspectj可能会产生一些副作用(例如,人们会写一些关于性能的负面消息)。我不知道如何使用注释来实现这一点。因此,我建议重构代码,从另一个类调用事务方法,或者以编程方式管理事务。我认为AspectJ是一种极端的手段。