获取LazyInitializationException"无法初始化代理 - 没有会话"在后台线程中运行事务时

时间:2014-11-12 18:03:21

标签: multithreading spring hibernate jpa

我有一个奇怪的问题:

假设我有两个实体类,例如ContainerContainedObjectContainer@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
    }
}

ContainerRepositoryPagingAndSortingRepository。运行doInForeground成功,但submitToBackground会抛出众所周知的LazyInitializationException“无法初始化代理 - 无会话”

好像没有启动任何交易或者关闭太快。使用@Transactional注释任何方法都无济于事。

是否根本无法在后台线程中使用Spring-JPA,还是需要额外的魔法?

1 个答案:

答案 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