【问题标题】:Spring Data JPA, Hibernate, @ManyToOne(fetch=FetchType.LAZY) and org.hibernate.LazyInitializationException: could not initialize proxy - no SessionSpring Data JPA、Hibernate、@ManyToOne(fetch=FetchType.LAZY) 和 org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话
【发布时间】:2016-10-25 08:58:39
【问题描述】:

Employee and Phone example

如何使 Hibernate Lazy 初始化工作(在 Spring Boot 中)?

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at com.example.domain.Employee_$$_jvstb7e_2.toString(Employee_$$_jvstb7e_2.java) ~[bin/:na]
    at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_74]
    at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_74]
    at com.example.domain.Phone.toString(Phone.java:13) ~[bin/:na]
    at com.example.SpringBootQuerydslTestBean$1.run(SpringBootQuerydslTestBean.java:49) ~[bin/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:806) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
    ... 6 common frames omitted

Java code

public class Phone {
    ...
    @ManyToOne(fetch=FetchType.LAZY)
    private Employee owner;

附: 一些建议使用FetchType.EAGER,如org.hibernate.LazyInitializationException: could not initialize proxy - no Session, 但让延迟加载工作(在 Spring Boot、Spring Data JPA 中)正是我的目标。

【问题讨论】:

  • 你试过 current_session_context_class --> 线程吗?
  • 你有 repository.impl 类吗?您可以从 JPA 查询中获取数据。
  • 创建一个正确的toString,它不包含反向引用。问题是你正在记录一些东西(我猜)......再次具有潜在危险,因为当它工作时你可能会遇到堆栈溢出异常,因为 Pone 引用 Employee 有一个 toString 可能再次引用 Phone并获得一次又一次。

标签: java hibernate jpa spring-boot lazy-loading


【解决方案1】:

发生这种情况是因为 Lombok 指令 @Data,而不是它,使用 @Getter 和 @Setter, 关注@Data 中的 javadocs:

等效于@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode。

@ToString 指令为整个类生成 toString 方法的实现,因此在您的 JPA 返回中需要包含所有对象的数据。

【讨论】:

    【解决方案2】:

    感谢 M. Deinum 的提示。

    这个特殊情况 已通过在Employee 中添加toString() 以重新定义Lombok toString() 来解决

    @Override
        public String toString() {
            return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]";
        }
    

    还有specifying exactly Fetch type

    代码https://github.com/paulvi/spring-boot-querydsl

    【讨论】:

    • 您也可以使用 Lombok 并从 Phone 中明确排除 employee 字段,这应该可以解决问题。
    【解决方案3】:

    我认为您正在尝试在当前会话分离时从代理中获取孩子, 你可以在同一个会话中得到懒惰的孩子。

    【讨论】:

    • 如何通过 JPA 使用 Spring Data 存储库从 Spring Boot 控制会话(即 Hibernate 事物)?
    猜你喜欢
    • 1970-01-01
    • 2016-07-29
    • 2014-01-14
    • 2021-03-13
    • 2011-12-01
    • 2014-04-21
    • 2019-05-10
    • 2015-11-09
    • 2021-08-10
    相关资源
    最近更新 更多