JPA @OneToOne with Shared ID——我能做得更好吗? [英] JPA @OneToOne with Shared ID -- Can I do this Better?

查看:26
本文介绍了JPA @OneToOne with Shared ID——我能做得更好吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用我不想更改的现有架构.该模式在表 Person 和 VitalStats 之间存在一对一的关系,其中 Person 有一个主键,VitalStats 使用相同的字段作为其主键和外键到 Person,这意味着它的值是对应的 PK 的值人.

这些记录是由外部进程创建的,我的 JPA 代码从不需要更新 VitalStats.对于我的对象模型,我希望我的 Person 类包含一个 VitalStats 成员,但是:

当我尝试

@Entity公共类人{私人长ID;@ID公共长 getId(){ 返回 id;}私人 VitalStats 对比;@OneToOne(mappedBy = 人")public VitalStats getVs() { return vs;}}@实体公共类 VitalStats{私人 人 人;@OneToOne公共人 getPerson() { 返回人;}}

我遇到的问题是 VitalStats 缺少 @Id,这对 @Entity 不起作用.

如果我尝试

@Id @OneToOne公共人 getPerson() { 返回人;}

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

我可以制作 VitalStats @Embeddable 并通过 @ElementCollection 将其连接到 Person,但随后它必须作为集合访问,即使我知道只有一个元素.可行,但有点烦人和有点混乱.

那么是什么阻止我说 Person 实现了 Serializable 呢?没有什么,真的,除了我喜欢我代码中的所有东西都是有原因的,我看不到任何逻辑,这降低了我的代码的可读性.

与此同时,我只是用一个长的 personId 替换了 VitalStats 中的 Person 字段,并制作了 VitalStats 的 @Id,所以现在 @OneToOne 可以工作了.

所有这些对(对我来说)看似简单的问题的解决方案都有些笨拙,所以我想知道我是否遗漏了什么,或者是否有人至少可以向我解释为什么 Person 必须是可序列化的.

TIA

解决方案

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

Hibernate 参考文档的相关部分:

PrimaryKeyJoinColumn <块引用>

PrimaryKeyJoinColumn 注释确实说明了该实体用作关联实体的外键值.

MapsId <块引用>

MapsId 注释要求 Hibernate 从另一个关联实体.在 Hibernate 行话中,它被称为外部生成器,但 JPA 映射读取更好,值得鼓励

Person.java

@Entity公共类人{@ID@GeneratedValue(策略 = GenerationType.IDENTITY)@Column(name = "person_id")私人长ID;@OneToOne(cascade = CascadeType.ALL)@PrimaryKeyJoinColumn私人 VitalStatsvitalStats;}

VitalStats.java

@Entity公共类 VitalStats{@Id @Column(name="vitalstats_id") 长id;@MapsId@OneToOne(mappedBy = "vitalStats")@JoinColumn(name = "vitalstats_id")//与id同名@Column私人 人 人;私人字符串统计;}

人员数据库表

创建表人(person_id bigint(20) NOT NULL auto_increment,名称 varchar(255) 默认为 NULL,主键(`person_id`))

VitalStats 数据库表

创建表vitalstats(vitalstats_id bigint(20) 非空,统计 varchar(255) 默认为 NULL,主键(`vitalstats_id`))

I’m working with an existing schema that I’d rather not change. The schema has a one-to-one relationship between tables Person and VitalStats, where Person has a primary key and VitalStats uses the same field as both its primary key and its foreign key to Person, meaning its value is the value of the corresponding PK of Person.

These records are created by external processes, and my JPA code never needs to update VitalStats. For my object model I’d like my Person class to contain a VitalStats member, BUT:

When I try

@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; }
}

I have the problem that VitalStats lacks an @Id, which doesn’t work for an @Entity.

If I try

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

that solves the @Id problem but requires that Person be Serializable. We’ll get back to that.

I could make VitalStats @Embeddable and connect it to Person via an @ElementCollection, but then it would have to be accessed as a collection, even though I know that there’s only one element. Doable, but both a little bit annoying and a little bit confusing.

So what’s preventing me from just saying that Person implements Serializable? Nothing, really, except that I like everything in my code to be there for a reason, and I can’t see any logic to this, which makes my code less readable.

In the meantime I just replaced the Person field in VitalStats with a long personId and made that VitalStats’s @Id, so now the @OneToOne works.

All of these solutions to what seems (to me) like a straightforward issue are a bit clunky, so I’m wondering whether I’m missing anything, or whether someone can at least explain to me why Person has to be Serializable.

TIA

解决方案

To map one-to-one association using shared primary keys use @PrimaryKeyJoinColumn and @MapsId annotation.

Relevant sections of the Hibernate Reference Documentation:

PrimaryKeyJoinColumn

The PrimaryKeyJoinColumn annotation does say that the primary key of the entity is used as the foreign key value to the associated entity.

MapsId

The MapsId annotation ask Hibernate to copy the identifier from another associated entity. In the Hibernate jargon, it is known as a foreign generator but the JPA mapping reads better and is encouraged

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;
}

Person Database Table

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

VitalStats Database Table

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

这篇关于JPA @OneToOne with Shared ID——我能做得更好吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆