【问题标题】:Hibernate: LazyInitializationException: failed to lazily initialize a collection of role. Could not initialize proxy - no SessionHibernate: LazyInitializationException: 延迟初始化角色集合失败。无法初始化代理 - 没有会话
【发布时间】:2017-08-13 01:01:45
【问题描述】:

我有下一个错误: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 上的大量答案,但没有任何用处。

可能是什么原因造成的?

【问题讨论】:

  • 当你说“事务存在于这一步”时,你的意思是你已经检查了一个事务是否真的打开了,比如使用stackoverflow.com/a/42584751/3517383?
  • @gabrielgiussi 是的
  • 实体是新对象吗?如果是这种情况,则必须先将实体对象保存在数据库中,然后才能将其添加到实体列表中。
  • 我猜你错了,实际上调用 model.getEntities() 给了我关于延迟初始化的同样错误

标签: java spring hibernate jpa spring-transactions


【解决方案1】:

正如@Maciej Kowalski 在第一次读取我的@Transactional 后提到的model 它已经处于分离状态并调用从另一个@Transactional 获取entities 方法失败LazyInitializationException

我已经稍微改变了我的服务,以便在同一个事务中从数据库中获取model

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

现在一切正常。

【讨论】:

    【解决方案2】:

    看起来模型是一个分离的实体。

    尝试合并并在合并实例上执行操作:

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

    【讨论】:

    • 确实,或者在调用所有其他服务的初始服务中打开事务。
    • 其实我不想使用会话对象。就在调用过程之前,我正在做 modelService.getModelById(modelId);它从数据库中返回我的对象​​
    • 好的,但是我假设这是在一个单独的事务中完成的。一旦你调用 process 方法,模型已经是一个分离的实体,持久性提供者不再管理它。你必须把它合并回来。或者只是在 process 方法中进行查询。
    • 感谢您的回答帮助。向我的处理方法添加了查询
    猜你喜欢
    • 2015-04-01
    • 2014-05-14
    • 2014-05-14
    • 2016-06-04
    • 2018-11-21
    • 2014-12-23
    • 2017-01-30
    • 1970-01-01
    • 2020-03-18
    相关资源
    最近更新 更多