一尘不染

具有共享ID的JPA @OneToOne —我可以做得更好吗?

java

我正在使用一个我不想更改的现有架构。该模式在表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


阅读 348

收藏
2020-09-08

共1个答案

一尘不染

要使用共享主键映射一对一关联,请使用@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`)
)
2020-09-08