Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 获取LazyInitializationException“;无法初始化代理-无会话“;在后台线程中运行事务时_Multithreading_Spring_Hibernate_Jpa - Fatal编程技术网

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是一种极端的手段。