Spring Boot JPA - OneToMany关系导致无限循环

Sma*_*ajl 6 java hibernate jpa spring-boot

我有一个简单的@OneToMany关系的两个对象,如下所示:

父:

@Entity
public class ParentAccount {

  @Id
  @GeneratedValue
  private long id;
  private String name;

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "parentAccount")
  private Set<LinkedAccount> linkedAccounts;

}
Run Code Online (Sandbox Code Playgroud)

儿童:

@Entity
public class LinkedAccount {

  @Id
  @GeneratedValue
  private long id;

  @ManyToOne(optional = false)
  private ParentAccount parentAccount;

  private String name;

  // empty constructor for JPA
  public LinkedAccount() {
  }

}
Run Code Online (Sandbox Code Playgroud)

我使用Spring CrudRepository来操作这些实体.然而,当调用时ParentAccount parent = parentAccountRepository.findOne(id);,某种无限循环开始发生,并且hibernate在整个控制台上发送垃圾邮件:

Hibernate: select linkedacco0_.parent_account_id as parent_a6_1_0_, linkedacco0_.id as id1_0_0_, linkedacco0_.id as id1_0_1_, linkedacco0_.aws_id as aws_id2_0_1_, linkedacco0_.key_id as key_id3_0_1_, linkedacco0_.name as name4_0_1_, linkedacco0_.parent_account_id as parent_a6_0_1_, linkedacco0_.secret_key as secret_k5_0_1_ from linked_account linkedacco0_ where linkedacco0_.parent_account_id=?
Run Code Online (Sandbox Code Playgroud)

我尝试将获取类型更改为LAZY,但后来我收到此错误:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.berrycloud.scheduler.model.ParentAccount.linkedAccounts, could not initialize proxy - no Session
Run Code Online (Sandbox Code Playgroud)

(似乎它试图在事务上下文之外进行延迟加载).

这是我的CRUD存储库:

@Repository
public interface ParentAccountRepository extends CrudRepository<ParentAccount, Long> {
}
Run Code Online (Sandbox Code Playgroud)

有人能告诉我如何解决这个问题吗?我更喜欢EAGER fetch的解决方案.谢谢你的任何提示

编辑:这是我正在使用的架构

CREATE TABLE parent_account (
    id BIGINT auto_increment,
    name VARCHAR(80) null,
    PRIMARY KEY (`id`)
);

CREATE TABLE linked_account (
    id BIGINT auto_increment,
    parent_account_id BIGINT,
    name VARCHAR(80) null,
    FOREIGN KEY (`parent_account_id`) REFERENCES `parent_account` (`id`),
    PRIMARY KEY (`id`)
);
Run Code Online (Sandbox Code Playgroud)

小智 18

第一个答案表明:

不要@Data@Entity类上使用Lombok的注释.

原因: @Data生成hashcode(),equals()以及toString()使用生成的getter的方法.使用getter方法当然即使属性标记为FetchType = LAZY也会获取新数据.

在某个地方,hibernate尝试使用toString()它来记录数据并且崩溃.

  • Lombok确实是内存模型创建无限循环的原因,并且在我的情况下最终导致StackOverflowError.尽管如此,我发现龙目岛的吸气剂和制定者太有用了,完全没有放弃它.因此,我只通过将我自己的_toString()_方法添加到刚刚返回_super.toString()_的类来禁用Lombok生成_toString()_,它解决了我的问题. (2认同)
  • 您仍然可以使用Lombok排除您的惰性提取字段。`@EqualsAndHashCode(exclude = {“ firstLazyField”,“ secondLazyField”})`和`@ToString(exclude = {“ firstLazyField”,“ secondLazyField”}))` (2认同)

Sma*_*ajl 6

问题解决了.我@toString在LinkedAccount中使用了一个引用ParentAccount 的自定义方法.我不知道这可能会导致任何问题,因此我没有在我的问题中包含toString.

显然,这导致延迟加载的无限循环,并删除此引用解决了问题.