[英]JPA: Polymorphic association and Joined table
我对 Hibernate 和 JPA 还很陌生。 我有一个与 EntityInformation 有一对一关系的 Identity 类,它被子类为 PersonalInformation 或 CompanyInformation。
我正在尝试使用联接表策略来保持 DRY,以便数据库中的基本 EntityInformation 表具有公共字段,而 PersonalInformation 和 CompanyInformation 表仅具有特定于类的字段
当我创建一个“公司”类型的身份时,我想为该身份创建一个 CompanyInformation。 我遇到的问题是,当我创建身份时,会保留一个实体信息,但不会保留个人/公司信息。
这可能吗? 我觉得我错过了一些东西或需要以不同的方式建模。 任何帮助将不胜感激!
这是我的身份类:
@Entity
@Table(name = "identities")
public class Identity {
@NotNull
@Enumerated(EnumType.STRING)
// type is either Personal or Company
private IdentityType type;
@NotNull
@OneToOne(
mappedBy = "identity", cascade = CascadeType.ALL, orphanRemoval = true, optional = false)
private EntityInformation entityInformation;
...
}
实体信息类:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "entity_informations")
public class EntityInformation {
@NotNull private Boolean hasTaxPayerId;
@OneToOne(optional = false)
@JoinColumn(name = "identity_id", nullable = false)
private Identity identity;
...
}
个人信息类:
public class PersonalInformation extends EntityInformation{
@NotBlank private String firstName;
@NotBlank private String lastName;
private String middleName;
...
}
公司信息类:
public class CompanyInformation extends EntityInformation{
@NotBlank private String name;
...
}
你的身份表有点混乱。 它与实体具有一一关系并指定实体类型。 在设计的这一点上,最好对架构进行非规范化并将类型保留在实体中。
优点:更好的性能(不是额外的连接)、清晰和更少的级联问题开销。
您可以在 EntityInformation 中添加一个具有类型的新字段,并在子实体中定义它(如果需要)。
除了我没有看到ids
之外,设计看起来不错。 您应该在Identity
上删除optional = false
。 该属性仅用于检索,因为EntityInformation
是关系的所有者,并且没有为此放入Identity
架构中。 它会导致鸡和蛋的问题 b/c 你不能创建两个新实体并将它们保存在同一个事务中 b/c 都不能为空但一个必须在另一个之前保存。 我对其进行了测试,它为我EntityInformation
和CorporateInformation
。
@Entity
public class Identity {
@Id @GeneratedValue
private Long id;
@OneToOne(mappedBy = "identity", cascade = CascadeType.ALL, orphanRemoval = true)
private InformationBase information;
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class InformationBase {
@Id @GeneratedValue
private Long id;
@OneToOne(optional = false)
@JoinColumn(name = "identity_id", nullable = false)
private Identity identity;
@Entity
public class CorporateInformation extends InformationBase {
并使用它:
tx.begin();
Identity identity = new Identity();
CorporateInformation corporateInformation = new CorporateInformation();
corporateInformation.setIdentity(identity);
em.persist(identity);
em.persist(corporateInformation);
tx.commit();
在日志中显示
Hibernate: create table CorporateInformation (id bigint not null, primary key (id))
Hibernate: create table Identity (id bigint not null, primary key (id))
Hibernate: create table InformationBase (id bigint not null, identity_id bigint not null, primary key (id))
Hibernate: create table PersonalInformation (id bigint not null, primary key (id))
Hibernate: alter table InformationBase drop constraint if exists UK_s2ny1w2e3fpckgv97n4bhe49h
Hibernate: alter table InformationBase add constraint UK_s2ny1w2e3fpckgv97n4bhe49h unique (identity_id)
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: alter table CorporateInformation add constraint FKq69d75va3x785scp4iki8kprs foreign key (id) references InformationBase
Hibernate: alter table InformationBase add constraint FK9g3vjjvp7ohn3dfirh6u8mwrx foreign key (identity_id) references Identity
Hibernate: alter table PersonalInformation add constraint FK6muqauf869dw0x9jb7jlhcpwo foreign key (id) references InformationBase
Hibernate: call next value for hibernate_sequence
Hibernate: call next value for hibernate_sequence
Hibernate: insert into Identity (id) values (?)
Hibernate: insert into InformationBase (identity_id, id) values (?, ?)
Hibernate: insert into CorporateInformation (id) values (?)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.