Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate中的自引用多关系_Java_Hibernate_Many To Many - Fatal编程技术网

Java Hibernate中的自引用多关系

Java Hibernate中的自引用多关系,java,hibernate,many-to-many,Java,Hibernate,Many To Many,我正在寻找一种在Hibernate中为同一类的两个或多个对象之间的关系建模的方法。例如:我想创建一个情景,在这里我想模拟人与人之间的关系。在数据库中,我有两个表: 人: 身份证 名字 关系: 父Id 儿童Id 我试图在Hibernate中对此进行建模,因为一个人有两个多个关系(Getter/Setter注释是Lombok): @Getter @塞特 @建筑商 @AllArgsConstructor @诺尔格构装师 @实体 @表(name=“persons”) 公共阶层人士{ @身份证 @

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

人:

  • 身份证
  • 名字
关系:

  • 父Id
  • 儿童Id
我试图在Hibernate中对此进行建模,因为一个人有两个多个关系(Getter/Setter注释是Lombok):

@Getter
@塞特
@建筑商
@AllArgsConstructor
@诺尔格构装师
@实体
@表(name=“persons”)
公共阶层人士{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私人长Id
@列(name=“name”)
私有字符串名称;
@ManyToMany(fetch=FetchType.LAZY)
@可接合(
name=“关系”,
joinColumns={@JoinColumn(name=“parent_id”,nullable=false)},
inverseJoinColumns={@JoinColumn(name=“child\u id”,nullable=false)}
)
private Set children=new HashSet();
@ManyToMany(fetch=FetchType.LAZY)
@可接合(
name=“关系”,
joinColumns={@JoinColumn(name=“child_id”,nullable=false)},
inverseJoinColumns={@JoinColumn(name=“parent\u id”,nullable=false)}
)
private Set parents=new HashSet();
}
这给了我以下问题:

  • 对于获取类型“LAZY”,Hibernate抱怨调用person.getChildren()或person.getParents()时没有会话
  • 对于fetch类型“EAGER”,Hibernate为集合返回null,这会在尝试添加子项或父项时导致null指针。我担心的另一件事是可能的无休止的递归抓取
为了解决这个问题,我尝试将关系建模为一个类,这样我就可以使用PersonRepository中的JPA查询来查找孩子和家长,而不必处理许多复杂的问题:

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);
}
公共接口PersonRepository扩展了JpaRepository{
@质疑(
“从p.id=r.childId上的人员p连接关系r中选择p,其中r.childId=:childId”
)
列出findParents(长childId);
}
这导致Hibernate抱怨关系没有@Id字段。我不想添加这一点,因为数据库中的关系表应该为关系建模,而不是拥有自己的id

当我试图在Hibernate中在线搜索类似的结构时,我通常会在中找到经典的多对多示例和问题,比如两个不同类之间的关系,而不是同一类的两个对象之间的关系

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


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

我不确定我是否理解正确,但我曾经遇到过类似的情况。 我所做的是保留没有关系的子/父对象,并在之后用它们的关系更新它们(仍然在同一事务中)

private void insertEntity(最终抽象实体){
insertedEntities.add(entity.getId());
最终列表关系=entity.onBeforeInsertion();
for(最终抽象实体关系:关系){
如果(!insertedEntities.contains(relation.getId())){
插入性(关系);
}
}
最终RelationBundle RelationBundle=新RelationBundle();
实体.onInsertion(relationBundle);
立即通过代理(实体)提交第十二份报告;
for(最终抽象实体关系:关系){
实体.onRelationInsertion(关系,关系束);
}
dao.saveOrUpdate(实体);
}
通过代理(最终文件实体)立即撤销私有所有权{
proxiedAccess()。立即安全性(实体);
}
私有MyConsumer代理访问(){
返回applicationContext.getBean(getClass());
}
@事务性(传播=传播。需要\u新建)
立即失效的公共文件(最终文件实体){
试一试{
如果(!dao.entityExistsFromId((int)entity.getId()){
保存(实体);
}
}捕获(最终异常e){
error(“保存实体时出错:{}”,entity.getId(),e);
}
}

当涉及到在链接表中使用类型字段时,我的回答可能会有好处:谢谢,但这映射了两个不同类之间的许多关系。我正在尝试将Persons映射到Persons。我尝试过这样做,但是Person.getChildren返回null,根据我的理解,这是不应该发生的。我能做些什么来澄清这个问题?只有在更新以某种方式失败的情况下才会发生这种情况。如果您使用的是Spring,则可能需要一个新的代理实例。参考:并用一些代码更新了答案。像
onBeforeXXX
这样的事件只是删除关系并将它们保存到一个Bundle中。我求助于modellig,将关系作为一个单独的带有Id的关系,并使用两个long作为父Id和子Id。这个项目很匆忙。关系存储库有基于子id获取父id的方法,我使用这些id获取实际的person对象。次优,但不会影响即时抓取的性能,也不会导致过期会话出现问题。我真的很想把这个项目迁移到MyBatis。
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);
}
 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);
    }
}