没有会话的休眠 FetchType.LAZY
Posted
技术标签:
【中文标题】没有会话的休眠 FetchType.LAZY【英文标题】:Hibernate FetchType.LAZY without session 【发布时间】:2015-07-03 09:45:47 【问题描述】:我在 Spring Web 应用程序中遇到很多 LazyLoadingException
问题,无论我尝试访问带有 FetchType.LAZY
注释的字段
Spring 中没有配置会话,因为要求 API 应该是无状态的。
所有服务层方法都正确设置了@Transactional
注释。
但是,当我尝试访问任何域对象上的惰性字段时,我得到了著名的 LazyInitializationException (...) could not initialize proxy - no Session
我认为当我使用 @Transactional
方法时,Hibernate 会在需要时自动加载惰性字段,但它似乎没有。
我花了几天的时间寻找答案,但没有一个能满足我的需要。我发现 Spring 可以使用 openSessionInViewFilter 进行配置,但它似乎会导致很多问题,而且我没有任何会话。
如何在@Transactional
annotated 服务方法中自动加载惰性字段,这样的无状态API?
我确定我在这里遗漏了一些明显的东西,但我对 Spring 和 Hibernate 不是很熟悉。
如果我的问题中缺少我应该给你的信息,请告诉我。
【问题讨论】:
您正在混合会话和无状态,但是这里的会话是休眠会话而不是 http 会话,因此与有状态或无状态的任何内容都无关。所以是的,您确实有会话,您没有HttpSession
,但你有来自休眠的Session
。 2 种不同的东西。
好的,谢谢您的澄清。因此,如果 Hibernate 会话确实存在,为什么 Hibernate 不使用它来检索惰性字段,而是抛出 LazyInitializationException ?
因为那个时候,交易之后,它就不存在了。它绑定到事务边界,除非您使用OpenSessionInViewFilter
。要么使用它,要么在 @Transactional
带注释的方法中正确准备模型。
“我认为当我在 @Transactional 方法中需要时,Hibernate 会自动加载惰性字段” 是的,它应该自动加载它们。看来你还没有整合好Spring with Hibernate。
@singe31 一个简单的方法是调试您的应用程序。然后,您将看到 spring 创建的代理作为调用堆栈的一部分。
【参考方案1】:
LazyInitializationExceptions
是一种代码味道,就像EAGER fetching 一样。
首先,获取策略应该是基于业务案例的查询。 Tha DAO 层仅负责获取正确的关联,因此:
您应该对所有 many-to-one
关联和最多一个一对多关联使用 FETCH
指令。如果您尝试 JOIN FETCH 多个一对多关联,您将获得笛卡尔积,您的应用程序性能将受到影响。
如果您需要获取多个集合,那么multi-level fetching 更合适。
您应该问自己为什么要从 DAO 层返回实体。使用 DTO 是一个更好的选择,因为它既减少了从数据库中获取的数据量,又不会将实体抽象泄漏到 UI 层中。
【讨论】:
这似乎不是一种非常干净的编码方式。使用它我需要在服务层的任何地方添加一堆初始化。在我看来,这会使代码非常难以阅读和维护。你个人到处都写这样的声明吗? 感谢您的建议。我认为它不会解决我的问题,但是当我设法解决我的问题时,它将有助于使应用程序性能更好。关于 DTO ,我正在使用它们,但我看不出它们如何减少数据库访问,因为它们是使用域对象中的 Builder 模式实例化的。因此,在构建 DTO 时,所有数据都已获取,对吗?我没有使用 DTO 编写应用程序的那一部分,但在我看来那里存在一个大问题。 Hibernate 应该如何填充 DTO? Hibernate 支持“select new package.DTO(id, name) from entity”语法,因此您可以根据需要获取尽可能多的数据。这也可以减少查询延迟。 好,我不知道。这是否意味着我必须为每个 DTO 编写自定义 hql 查询?是否存在将 DTO 字段映射到域对象字段的某种方式,这样 Hibernate 会自动仅检索 DTO 中具有现有字段的数据? 幸运的是,还有另一种选择。您可以为同一个数据库表定义多个实体:Employee、EmployeeFullName、EmployeeAddress。这样,您可以将完整的实体和一些子实体映射到主数据库行的子集。以上是关于没有会话的休眠 FetchType.LAZY的主要内容,如果未能解决你的问题,请参考以下文章