我正在使用一个我不想改变的现有架构。表格Person和VitalStats之间具有一对一的关系,其中Person有一个主键,VitalStats使用相同的字段作为其主键和它的外键到Person,这意味着它的值是相应PK的值人。
这些记录是由外部进程创建的,我的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缺少@Id,这对@Entity不起作用。\
如果我尝试
@Id @OneToOne
public Person getPerson() { return person; }
解决了@Id问题,但要求Person是Serializable。我们会回过头来看。
我可以制作VitalStats @Embeddable并通过@ElementCollection将它连接到Person,但是它必须作为集合访问,即使我知道只有一个元素。可行,但既有点烦人又有点混乱。
那么是什么阻止我只是说Person实现了Serializable?没什么,真的,除了我喜欢我的代码中的所有东西都是有原因的,并且我看不到任何逻辑,这使得我的代码不那么可读。
与此同时,我只是用一个很长的人替换了VitalStats中的Person字段并制作了VitalStats的@Id,所以现在@OneToOne正常工作。
所有这些解决方案似乎(对我来说)像一个直截了当的问题都有点笨拙,所以我想知道我是否遗漏了什么,或者是否有人至少可以向我解释为什么人必须是可序列化的
TIA
答案 0 :(得分:86)
要使用共享主键映射一对一关联,请使用@PrimaryKeyJoinColumn
和@MapsId
注释。
Hibernate参考文档的相关部分:
PrimaryKeyJoinColumn注释确实说明了主键 该实体用作关联实体的外键值。
MapsId注释要求Hibernate从中复制标识符 另一个相关实体。在Hibernate术语中,它被称为a 外部生成器,但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`)
)
答案 1 :(得分:15)
就我而言,这就是诀窍:
家长班:
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;
}
儿童班:
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;
}