我正在使用一个我不想更改的现有架构。该模式在表Person和VitalStats之间具有一对一关系,其中Person具有主键,而VitalStats使用相同的字段作为其主键和针对Person的外键,这意味着其值是相应PK的值人。
这些记录是由外部流程创建的,我的JPA代码从不需要更新VitalStats。对于我的对象模型,我希望我的Person类包含VitalStats成员BUT:
当我尝试
@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缺少@Id,这对于@Entity无效。\
如果我尝试
@Id @OneToOne public Person getPerson() { return person; }
解决了@Id问题,但要求Person可序列化。我们将回到这一点。
我可以使VitalStats @Embeddable并通过@ElementCollection将其连接到Person,但是即使我知道只有一个元素,也必须将其作为一个集合进行访问。可行,但是既令人讨厌又令人困惑。
那么,是什么阻止了我只是说Person实现了Serializable?没什么,实际上,除了我喜欢代码中的所有内容是有原因的,而且我看不到任何逻辑,这使得我的代码可读性较差。
同时,我只是将VitalStats中的Person字段替换为一个长的personId,并使其成为VitalStats的@Id,所以现在@OneToOne可以使用。
所有这些解决方案(在我看来)都是一个简单的问题,有些笨拙,因此我想知道我是否缺少任何内容,或者是否有人至少可以向我解释为什么Person必须可序列化。
TIA
要使用共享主键映射一对一关联,请使用@PrimaryKeyJoinColumn和@MapsId注释。
@PrimaryKeyJoinColumn
@MapsId
Hibernate参考文档的相关部分:
PrimaryKeyJoinColumn
PrimaryKeyJoinColumn注释确实表示该实体的主键用作关联实体的外键值。
MapsId
MapsId注释要求Hibernate从另一个关联的实体复制标识符。在Hibernate行话中,它被称为外来生成器,但JPA映射读起来更好,值得鼓励
人.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`) )