JPA @OneToOne共享ID – 我可以做得更好吗?

我正在使用一个我不想改变的现有模式。 该模式在表Person和VitalStats之间具有一对一的关系,其中Person具有主键,并且VitalStats使用相同的字段作为其主键和对于Person的外键,这意味着其值是相应的PK的值人。

这些logging是由外部进程创build的,我的JPA代码永远不需要更新VitalStats。 对于我的对象模型,我希望我的Person类包含一个VitalStats成员,但是:

当我尝试

@Entity public class Person{ private long id; @Id public long getId(){ return id; } private VitalStats vs; @OneToOne(mappedBy = “person”) public VitalStats getVs() { return vs; } } @Entity public class VitalStats{ private Person person; @OneToOne public Person getPerson() { return person; } } 

我有这个问题,VitalStats缺less一个@ Id,这不适用于@实体。

如果我尝试

 @Id @OneToOne public Person getPerson() { return person; } 

解决了@Id问题,但要求Person是可序列化的。 我们会回到这个。

我可以让VitalStats @Embeddable并通过@ElementCollection将它连接到Person,但是它将不得不作为一个集合来访问,即使我知道只有一个元素。 可以,但是有点烦人和有点混乱。

那么是什么阻止了我说Person实现了Serializable呢? 没有什么,真的,除了我喜欢我的代码中的所有内容,出于某种原因,我看不到任何逻辑,这使得我的代码不易读。

与此同时,我用一个很长的personIdreplace了VitalStats中的Person字段,并将其命名为VitalStats的@Id,所以现在@OneToOne可以工作。

所有这些解决scheme似乎(对我来说)像一个简单的问题是有点笨重,所以我想知道我是否失去了什么,或者至less有人能够解释为什么人必须是可序列化的。

TIA

要使用共享主键映射一对一关联,请使用@PrimaryKeyJoinColumn@MapsId批注。

Hibernate参考文档的相关章节:

PrimaryKeyJoinColumn

PrimaryKeyJoinColumn注释确实表示实体的主键用作关联实体的外键值。

MapsId

MapsId注解要求Hibernate从另一个关联实体复制标识符。 在Hibernate术语中,它被称为外部生成器,但是JPA映射读取得更好并受到鼓励

Person.java

  @Entity public class Person { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name = "person_id") private Long id; @OneToOne(cascade = CascadeType.ALL) @PrimaryKeyJoinColumn private VitalStats vitalStats; } 

VitalStats.java

 @Entity public class VitalStats { @Id @Column(name="vitalstats_id") Long id; @MapsId @OneToOne(mappedBy = "vitalStats") @JoinColumn(name = "vitalstats_id") //same name as id @Column private Person person; private String stats; } 

人员数据库表

 CREATE TABLE person ( person_id bigint(20) NOT NULL auto_increment, name varchar(255) default NULL, PRIMARY KEY (`person_id`) ) 

VitalStats数据库表

 CREATE TABLE vitalstats ( vitalstats_id bigint(20) NOT NULL, stats varchar(255) default NULL, PRIMARY KEY (`vitalstats_id`) ) 

在我的情况下,这使得伎俩:

父类:

 public class User implements Serializable { private static final long serialVersionUID = 1L; /** auto generated id (primary key) */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(unique = true, nullable = false) private Long id; /** user settings */ @OneToOne(cascade = CascadeType.ALL, mappedBy = "user") private Setting setting; } 

儿童class:

 public class Setting implements Serializable { private static final long serialVersionUID = 1L; /** setting id = user id */ @Id @Column(unique = true, nullable = false) private Long id; /** user with this associated settings */ @MapsId @OneToOne @JoinColumn(name = "id") private User user; }