休眠延迟加载不适用于@Transactional方法

时间:2019-05-10 13:31:25

标签: spring hibernate

我正面临太多讨论的“”

我正在使用hibernate开发Spring Boot应用程序。

据我所知,如果Entity的属性标记为FetchType.LAZY,则需要具有Hibernate会话才能触发相应的查询以带入相关实体。

以下是一种从父实体检索实体列表的方法:

@Transactional
public List<Portfolio> getSharedPortfolios(String userName){
    User user = userService.getUserActive(userName);
    List<Portfolio> sharedPortfolios = user.getSharedPortfolios();
    //logger.debug("Number of Shared Portfolios: " + sharedPortfolios.size());  <======
    return sharedPortfolios;
}

正在从控制器调用 getSharedPortfolios 方法并获取“ org.hibernate.LazyInitializationException”,然后尝试访问此列表(PersistentBag)

使用@Transactional注释进行注释的 getSharedPortfolios 方法,我希望在执行user.getSharedPortfolios()(sharedPortfolios是一个惰性获取列表)时,将初始化各个列表。但是不会发生这种情况。

有人可以向我解释为什么吗?而且,如果我取消注释打印该PersistentBag大小的日志行的注释,为什么不抛出异常?

在这种情况下,我需要使用EntityManager对其进行显式初始化吗?

非常感谢您。

2 个答案:

答案 0 :(得分:1)

调用List<Portfolio> sharedPortfolios = user.getSharedPortfolios();时,分配给sharedPortfolios的值是一个惰性代理。

如果您仅返回sharedPortfolios并在@Transactional方法之外访问它,则会得到LazyInitializationException

另一方面,如果您在sharedPortfolios方法中访问@Transactional,则会发生初始化,并返回已初始化的数据。

恕我直言,您描述的是预期的行为。

有多种强制提取的方法:

  • 实体图
  • jpql(提取)
  • 条件查询(获取)
  • 手动访问变量(如您的示例所示)

或者,检查设置 spring.jpa.open-in-view=true

答案 1 :(得分:0)

我不确定这是什么意思

  

“正在从控制器调用getSharedPortfolios方法”

因此可能不是您的情况,但是如果您从同一类中的另一个方法调用@Transactional方法,则getSharedPortfolios注释将不起作用。