当前位置: 首页 > 知识库问答 >
问题:

Hibernate中的自参照关系

徐飞尘
2023-03-14

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

人物:

    null
    null
@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<>();
}

这给了我以下问题:

  • 获取类型为“lazy”的Hibernate在调用person.getchildren()或person.getparaments()时抱怨没有会话
  • 具有“eager”fetch类型的Hibernate返回集合的null,这在试图添加子项或父项时会导致nullpointers。我担心的另一件事是,可能会出现没完没了的递归快速提取。

为了解决这个问题,我尝试将关系建模为一个类,这样我就可以在PersonRepository中使用JPA查询来查找孩子和父母,而不必处理复杂的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中同一个类的两个或多个对象之间的关系。我希望能够懒洋洋地去取关系,或者出于性能原因事后去取。

如果关系表可以有一个额外的字段“type”,它指示人(孩子、父母、侄子、朋友)之间的关系类型,这样就有空间容纳新的关系类型,而不会对数据库和代码进行太多更改,那就太好了。

共有1个答案

顾赞
2023-03-14

我不确定我是否理解你,但我有过一次类似的情况。我所做的是在没有关系的情况下持久化子/父,然后用它们的关系更新它们(仍然在同一个事务中)。

 private void insertEntity(final AbstractEntity entity) {
    insertedEntities.add(entity.getId());

    final List<AbstractEntity> relations = entity.onBeforeInsertion();
    for (final AbstractEntity relation : relations) {
        if (!insertedEntities.contains(relation.getId())) {
            insertEntity(relation);
        }
    }

    final RelationBundle relationBundle = new RelationBundle();
    entity.onInsertion(relationBundle);

    immediatelySaveNewEntityThroughProxy(entity);

    for (final AbstractEntity relation : relations) {
        entity.onRelationInsertion(relation, relationBundle);
    }

    dao.saveOrUpdate(entity);
}


private void immediatelySaveNewEntityThroughProxy(final DocumentEntity entity) {
    proxiedAccess().immediatelySaveNewEntity(entity);
}

private MyConsumer proxiedAccess() {
    return applicationContext.getBean(getClass());
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void immediatelySaveNewEntity(final DocumentEntity entity) {
    try {
        if (!dao.entityExistsFromId((int) entity.getId())) {
            dao.save(entity);
        }
    } catch (final Exception e) {
        LOGGER.error("Error saving entity: {}", entity.getId(), e);
    }
}
 类似资料:
  • 我有一个springboot应用程序,其中我有一个postgres数据库,里面有一个电影院列表: 这些影院中的每一个都显示一部或多部电影(在另一个数据库中)。我创建了一个关系表: 在最后一个表中,cinema_id是链接到cinemas表中id的外键。movie_id只是一个表示另一个数据库中的id的整数。 我的实体表示形式: 当我试着去看属于个人影院的电影时,问题就来了: null 我做错了什么

  • 孩子:@EDIT感谢@MithatKonuk 和家人:@EDIT感谢@米塔科努克 我想得到作为家庭一部分的孩子的名单。我尝试进行查询:@编辑感谢@MithatKonuk 当我尝试运行它时,总是会出现错误: 我需要你的帮助。 @编辑好的,所以我将此代码更新为完整的实体。你还需要更多吗?我很抱歉,也许这很容易,但是我正在学习Hibernate,我不知道这个cos出了什么问题。谢谢你的回答。

  • 问题内容: 我想将2个使用hibernate注释的实体与一个自定义连接子句关联起来。该子句具有通常的FK / PK相等性,但FK为null时也是如此。在SQL中,这类似于: 从我阅读的内容中,我应该在所有者实体上使用@WhereJoinTable批注,但是我对如何指定此条件感到困惑……尤其是它的第一部分-指的是联接实体的ID。 有人有例子吗? 问题答案: 这是一个使用标准父/子范例的示例,我认为应

  • 我们都知道,在spring-Hibernate应用程序中不使用@transactional注释会产生一个Hibernate异常: 线程“main”org.hibernate.hibernateException异常:无法获取当前线程的事务同步会话 我想知道“事务同步会话”是什么意思?

  • 在Java项目的build.gradle中,我有一个Maven存储库列表,用于相关性解析,如下所示: 储存库{ 谢了。

  • 我有两门课: 当我用UserRole保存User时,出现了一个奇怪的错误: 如果它创建了userrole_user_role_id,为什么要使用User_Role_ID?我该怎么修好它?