簡體   English   中英

JPA:多態關聯和連接表

[英]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 都不能為空但一個必須在另一個之前保存。 我對其進行了測試,它為我EntityInformationCorporateInformation

@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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM