当前位置: 首页 > 面试题库 >

休眠一对一实体关联,并在3个类之间共享PK

孙成化
2023-03-14
问题内容

我想要3个Java类的对象之间的 单向
一对一关系:“人到心脏”和“人到肝脏”。我希望对象共享相同的PK,即每个人都有相应的心脏和肝脏,其中person.person_id =
heart.heart_id =
liver.liver_id。我不想将3个表合并为1个表,因为每个表都有很多字段。这是我的代码(主要基于该问题的公认答案):

@Entity
public class Person {
   public long personId;
   private String name;
   public Heart heart;
   public Liver liver;
   // other fields

   @Id
   @GeneratedValue
   public long getPersonId() {return personId;}

   @OneToOne(cascade = CascadeType.ALL)
   @PrimaryKeyJoinColumn
   public Heart getHeart() {return heart;}

   @OneToOne(cascade = CascadeType.ALL)
   @PrimaryKeyJoinColumn
   public Liver getLiver() {return liver;}

   // other getters and setters and constructors
}


@Entity
public class Heart {
   private long heartId;
   private int bpm;
   private Person person;
   // other fields

   @Id
   @GenericGenerator(
      name = "generator",
      strategy = "foreign",
      parameters = @Parameter(name = "property", value = "person")
   )
   @GeneratedValue(generator = "generator")
   public long getHeartId() {return heardId;}

   @OneToOne(mappedBy="heart")
   @PrimaryKeyJoinColumn
   public Person getPerson() {return person;}

   // other getters and setters and constructors
}


@Entity
public class Liver {
   private long liverId;
   private boolean healthy;
   private Person person;
   // other fields

   // the rest uses the same hibernate annotation as Heart
}

我设置了会话并执行以下操作:

Person jack = new Person();
jack.setName("jack");
Heart heart = new Heart();
heart.setBpm(80);
Liver liver = new Liver();
liver.setHealthy(true);

然后,如果我将人对象与它的器官连接起来并保存,则会收到错误消息(注意:当我仅使用2个类(例如“人”和“心脏”)时,我会得到相同的行为):

jack.setHeart(heart);
jack.setLiver(liver);
session.save(jack);

org.hibernate.id.IdentifierGenerationException:尝试从空的一对一属性分配id:person

但是,如果我同时设置两种关系,它会起作用:

jack.setHeart(heart);
heart.setPerson(jack);
jack.setLiver(liver);
liver.setPerson(jack);
session.save(jack);

但是,对于单向关系,肯定不需要这样做吗?
干杯

ps。奇怪的是,当我仅使用2类(例如Person和Heart),并且以另一种方式设置链接时,我注意到它起作用(将两个对象都保存到DB中):

heart.setPerson(jack);
session.save(heart);

我不知道为什么这行得通(在我看来,Person是父对象,因为它自动生成自己的PK,而其他人使用它;所以这就是您应该设置的全部),但是无论如何我都无法弄清楚了解如何将这种工作方法应用于我的3类情况…


问题答案:

我不愿意告诉您这一点,但是您在那里存在双向关系。该人提及心脏和肝脏,并且每个人都提及该人。您在“心脏”和“肝脏”的Id属性上设置的注释专门表示它们通过委派给其Person属性来获得其Id属性的值。在显示的示例中,这些示例无效,您尚未在这些家伙上设置Person属性,因此,他们显然无法获取其Id值。

您可以将此关系设置为真正的单向OneToOne,这在Hibernate批注文档中进行了说明:

@Entity
public class Body {
    @Id
    public Long getId() { return id; }

    @OneToOne(cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    public Heart getHeart() {
        return heart;
    }
    ...
}


@Entity
public class Heart {
    @Id
    public Long getId() { ...}
}

或者,您可以稍微更改我们的实体对象,以简化连接关系的两侧,例如:

@Entity
public class Person {
   public long personId;
   private String name;
   public Heart heart;
   public Liver liver;
   // other fields

   @Id
   @GeneratedValue
   public long getPersonId() {return personId;}

   @OneToOne(cascade = CascadeType.ALL)
   @PrimaryKeyJoinColumn
   public Heart getHeart() {return heart;}

   public void setHeart(Heart heart){
      this.heart = heart;
      this.heart.setPerson(this);
   }

   @OneToOne(cascade = CascadeType.ALL)
   @PrimaryKeyJoinColumn
   public Liver getLiver() {return liver;}

   public void setLiver(Liver liver){
      this.liver = liver;
      this.liver.setPerson(this);
   }
   // other getters and setters and constructors
}


 类似资料:
  • 我正在开发一个Grails应用程序。我创建了3个实体客户,产品和订单。客户可以有许多订单,但每个订单只能包含单一产品。因此,单个订单可以关联到一个客户和一个产品。以下是我的域名: 顾客: 订单: 产品: 我使用generate all生成了控制器、视图,运行应用程序时出现以下错误: 我也不能创造一个客户。域映射有什么问题吗? 我的数据源配置如下:

  • 问题内容: 我想使用联接表在两个表之间建立一对多关系。 最后,我想使用Hibernate批注执行此操作。 我找到了一些使用xml映射执行此操作的示例,但没有带注释的示例。 我相信这就是需要创建表的方式 问题答案: 不要寻找例子。阅读官方文档: 另外,请注意,这是单向一对多关联的默认设置。因此,如果默认的表名和列名适合您,您甚至不必提供注释。

  • 问题内容: 当我使用@Entity注释类并尝试解决依赖关系时,我可以在两个不同的包javax.persistence.Entity和org.hibernate.annotations.Entity中选择包。 javax包是JPA的实体注释,但是为什么会有休眠的实体注释,它与JPA的注释有区别?仅仅是允许定义更多属性的扩展吗? 问题答案: 具有一些尚未标准化的额外属性。仅当直接使用hibernate

  • 问题内容: 有一个“ Item”类,它有一些相关的类,称为Vehicle,Vmodel,Category,ItemName,Brand,SizeModel。每个类都有属性ID和名称(例如Vehicle类,“ vid”和“ vname”)。 Item类具有itemcode。 另外,我还需要从给定的示例Item对象(称为“ ”)中获取Item对象,该对象等于我的示例item对象的属性以及与该对象关联的

  • 问题内容: 我有两个与多对多关联的表。 —数据库片段: 加载 ID 名称 会话 ID 日期 sessionsloads LoadId 的SessionID —hibernate映射片段: 为了从关联表 sessionloads中 删除一个条目,我执行以下代码: 但是,启动后,此代码将保持不变。 删除关联的正确方法是什么? 问题答案: 您需要更新和之间的链接的两端: 实际上,许多开发人员使用防御性方

  • 问题内容: 我有两个线程。可以调用修改变量的类的update方法。另一个调用读取该变量的类的update方法。只有一个线程写入,一个(或多个)线程读取该变量。由于我是多线程技术的新手,我需要在并发方面做什么? 谢谢, 问题答案: 如果有且仅有一个写线程,你可以逃脱使得它。否则,请查看答案。 仅在只有一个写线程的情况下才起作用,因为只有一个写线程,因此它始终具有的正确值。