Hibernate:LazyInitializationException:无法懒惰地初始化角色的集合。无法初始化代理 - 没有会话。

13

我遇到了这个错误:nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.Model.entities, could not initialize proxy - no Session

我的Model实体:

class Model {
...
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "model", orphanRemoval = true)
    @Cascade(CascadeType.ALL)
    @Fetch(value = FetchMode.SUBSELECT)
    public Set<Entity> getEntities() {
        return entities;
    }

    public void addEntity(Entity entity) {
        entity.setModel(this);
        entities.add(entity);
    }

}

而我有一个服务类:

@Service
@Transactional
class ServiceImpl implements Service {
    @Override
    public void process(Model model) {
        ...
        model.addEntity(createEntity());
        ...
    }
}

我正在从另一个服务方法调用服务:

@Override
@JmsListener(destination = "listener")
public void handle(final Message message) throws Exception {
    Model model = modelService.getById(message.getModelId());
    serviceImpl.process(model);
    modelService.update(model);
}

但是当我试图调用这个方法时,在entities.add(entity);一行上出现了异常,当我在model上调用getEntities()时也会发生相同的异常。我已经检查了事务管理器并且它已经正确地配置了,而且在这个步骤上存在事务。我还检查了与这个异常有关的大量stackoverflow答案,但没有什么有用的。

可能会导致这种情况的原因是什么?


当你说“此步骤存在事务”时,意味着你已经检查确实打开了事务,比如使用https://dev59.com/EVgQ5IYBdhLWcg3wi0o9#42584751? - gabrielgiussi
@gabrielgiussi 是的 - Orest
实体是否为新对象?如果是,你需要先在数据库中保存实体对象,然后再将其添加到实体列表中。 - Dimitri
我猜你错了,实际上调用model.getEntities()会给我同样关于lazyinitialization的错误。 - Orest
2个回答

9

看起来模型是一个独立的实体。

尝试将其合并到一个实例中并执行操作:

@Override
public void process(Model model) {
     ...
    Model mergedModel = session.merge(model);

    mergedModel.addEntity(createEntity());
    ...
}

确实,或者在一个调用所有其他服务的初始服务中打开事务。 - gabrielgiussi
1
实际上我不想使用session对象。在调用process方法之前,我执行modelService.getModelById(modelId); 并从数据库中返回对象。 - Orest
2
好的,但我假设这是在单独的事务中完成的。一旦调用process方法,模型已经是一个分离的实体,持久性提供程序不再管理它。您必须将其合并回来。或者只需在process方法内部进行查询。 - Maciej Kowalski
谢谢你的回答有所帮助。我已经在我的处理方法中添加了查询。 - Orest

7

正如 @Maciej Kowalski 在对我的 model 进行首次 @Transactional 读取后所提到的那样,它已经处于分离状态,从另一个 @Transactional 方法中获取 entities 的调用将导致 LazyInitializationException 异常。

我稍微修改了我的服务以在同一事务中从数据库中获取 model:

@Service
@Transactional
class ServiceImpl implements Service {
    @Override
    public void process(long modelId) {
        ...
        Model model = modelDao.get(modelId);
        model.addEntity(createEntity());
        ...
    }
}

现在一切都按预期工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接