在Hibernate中自引用ManyToMany关系

时间:2017-09-26 09:44:03

标签: java hibernate many-to-many

我正在寻找一种方法来模拟Hibernate中同一个类的两个或多个对象之间的关系。例如:我想创建一种我希望模拟人与人之间关系的情境。在数据库中,我有两个表:

人:

  • 编号
  • 名称

关联:

  • 家长ID
  • 儿童身份

我试图在Hibernate中对此进行建模,因为Person有两个ManyToMany关系(Getter / Setter注释是Lombok):

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "persons")
public class Person {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long Id

  @Column(name="name")
  private String name;


 @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(
      name = "relations",
      joinColumns = {@JoinColumn(name = "parent_id", nullable = false)},
      inverseJoinColumns = {@JoinColumn(name = "child_id", nullable = false)}
  )
  private Set<Person> children = new HashSet<>();

  @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(
      name = "relations",
      joinColumns = {@JoinColumn(name = "child_id", nullable = false)},
      inverseJoinColumns = {@JoinColumn(name = "parent_id", nullable = false)}
  )
  private Set<Person> parents = new HashSet<>();
}

这给了我以下问题:

  • 使用抓取类型&#34; LAZY&#34; Hibernate在调用person.getChildren()或person.getParents()
  • 时抱怨没有Session
  • 使用抓取类型&#34; EAGER&#34; Hibernate为集合返回null,这会在尝试添加子节点或父节点时导致nullpointers。我担心的另一件事是可能无休止的递归渴望。

为了解决这个问题,我尝试将Relation建模为一个类,这样我就可以在PersonRepository中使用JPA查询来查找Children和Parents,而不必混淆ManyToMany的复杂性:

public interface PersonRepository extends JpaRepository<Person, Long> {
  @Query(
      "select p from Person p join Relation r on p.id = r.childId where r.childId = :childId"
  )
  List<Person> findParents(Long childId);
}

这导致Hibernate抱怨Relation没有@Id字段。我不想添加它,因为数据库中的关系表应该建模关系,而不是自己的id。

当尝试在线搜索Hibernate中的类似结构时,我通常会在the documentation中找到经典的多对多示例以及this one之类的问题,其中两个不同的关系类而不是同一个类的两个对象之间的关系。

我正在寻找一种方法来模拟Hibernate中同一个类的两个或多个对象之间的关系。我希望能够懒惰地获取关系,或者出于性能原因在之后获取关系。

如果关系表可以有一个额外的字段&#34;类型&#34;那将是很好的。它表示人员(孩子,父母,侄子,朋友)之间的关系类型,这样就可以在没有对数据库和代码进行太多更改的情况下为新的关系类型留出空间。

1 个答案:

答案 0 :(得分:0)

我不确定我是否理解正确,但我曾经遇到过类似情况。 我所做的是坚持没有关系的孩子/父母,然后用他们的关系更新他们(仍在同一笔交易中)。

public class AWithB {
    @Embedded
    public A a;

    @Relation(parentColumn = "id", entityColumn = "aId", entity = B.class)
    public List<BWithC> bWithC;

    public AWithB() {}
}