Spring 数据 JPA、Hibernate、@ManyToOne(fetch=FetchType.LAZY) 和 org.hibernate.LazyInitializationException:无法初始化代理 - 无会话

Spring Data JPA, Hibernate, @ManyToOne(fetch=FetchType.LAZY) and org.hibernate.LazyInitializationException: could not initialize proxy - no Session

Employee and Phone example

如何使 Hibernate Lazy 初始化工作(在 Spring 引导内)?

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.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;

P.S。 有些人建议像 org.hibernate.LazyInitializationException: could not initialize proxy - no Session 那样使用 FetchType.EAGER, 但是让延迟加载工作(在 Spring Boot,Spring Data JPA 中)正是我的目标。

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

感谢 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 指令@Data,而不是它,使用@Getter 和@Setter, 关注来自@Data 的 javadocs:

Equivalent to @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode.

@ToString 指令为整个 class 生成了 toString 方法的实现,因此在您的 JPA 中 return 需要所有对象的数据。