LazyInitializationException:为什么 Hibernate 不能在延迟加载时创建会话?

LazyInitializationException : Why can't Hibernate create a session on lazy loading?

我的项目过去到处都有很多@Transactional 方法。现在由于业务逻辑,我不想在遇到问题时回滚,而是想将我的对象设置为错误状态(也就是保存在数据库中,所以绝对不会回滚),所以我删除了一些 @Transactional 以开始。

现在的问题是有延迟加载的地方没有会话,因此产生了 LazyInitializationException。

下面是我目前为止的以下故障排除和解决方案:

现在我的问题是:为什么 hibernate 不能自己做?这对我来说似乎微不足道,如果我使用延迟加载,我希望 Hibernate 创建一个会话(他在执行 Hibernate.initialize() 时似乎完全能够做到)自动加载日期。

有没有办法生成一个新的实体管理器以在我的方法中使用,这样 Hibernate 就不会一直创建和重新创建实体管理器?我真的觉得我缺少一些关于 Hibernate、延迟加载和会话的基本知识,这使得整个混乱变得不那么复杂了。

这是一个例子:

@Entity
@Table(name = "tata")
public class Tata {

    @Id
    @Column(name = "tata_id")
    private Long id;

    // getter / setter etc
}

@Entity
@Table(name = "toto")
public class Toto {

    @Id
    @Column(name = "toto_id")
    private Long id;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "tata_id")
    private Tata tata;

    // getter / setter etc
}

@Service("totoManager")
public class TotoManager extends GenericManagerImpl {

    @Autowired
    private EntityManager entityManager;
    @Autowired
    private TotoRepository totoRepository;

    public void doSomethingWithTotos() throws XDExceptionImpl {

        List<Toto> totos = this.totoRepository.findAll();

        for (toto toto : totos) {
        // LazyInitializationException here
            LOGGER.info("tata : " + toto.getTata().getId());
        }
    }
}

尝试阅读有关 在视图中打开会话 的内容,以了解为什么 延迟加载 在 session/transaction 中不起作用。如果你愿意,你可以设置 属性 spring.jpa.open-in-view=true 它会加载你的延迟加载数据。

Hibernate 可以自己完成。通过设置 属性 hibernate.enable_lazy_load_no_trans=true(对于 spring 引导,它应该是 spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true),您可以在事务关闭时加载任何惰性 属性。这种方法有一个很大的缺点:每次你加载延迟 属性,hibernate 打开会话并在后台创建事务。

我建议 entityGraphs 获取惰性属性。因此,您不必将持久上下文移动到更高级别或更改实体中的获取类型。