首页 > 解决方案 > 2个实体的不同双向@ManyToOne父级扩展了一些基本实体,但将基本实体数据保存在一个表中

问题描述

这个标题最接近我想要做的事情。:)

让我们从它在数据库中的外观(带有列的表)开始:

Email
  - id : PK
  - email : String
CompanyEmail
  - email_id : FK
  - company_id : FK
PersonEmail
  - email_id : FK
  - person_id : FK
Company
  - id : PK
Person
  - id : PK

现在让我们看一下模型:

@Entity
public class Company
{
    @Id
    @GeneratedValue
    private Long id;

    @OneToMany
    private List<CompanyEmail> emails = new ArrayList<>();
}

@Entity
public class Person
{
    @Id
    @GeneratedValue
    private Long id;

    @OneToMany
    private List<PersonEmail> emails = new ArrayList<>();
}

// Should this be @Entity? Maybe @MappedSuperclass? What strategy to use to be able to extend it?
public class Email // This is base email class/entity
{
    @Id
    @GeneratedValue
    private Long id;

    @javax.validation.constraints.Email
    private String email;
}

@Entity
public class PersonEmail // This needs to somehow extend Email, so all Email data is also accessible here.
{
    @ManyToOne
    private Person person;
}

@Entity
public class ComanyEmail // This needs to somehow extend Email, so all Email data is also accessible here.
{
    @ManyToOne
    private Company company;
}

现在我的问题是——在 Hibernate(最新)中是否有可能实现这样的结构?

上面设计时的要点(是什么驱使我):

注意:我也考虑过创建类似Contactable基类的东西,Comapny并且PersonEmail列表,但这不适合我的需要(每个表都没有类,也没有相同的表设计)。

我的问题是 - 有可能吗?即使我没有得到基于我给出的课程的例子的答案,只是事实会给我希望,我会找到它。

编辑 1

我是否应该在电子邮件表中使用鉴别器,然后将 FK 保留在那里?

Email
  - id : PK
  - email : String
  - companyOrPerson : FK
  - discriminator : Decides what FK points at
Company
  - id : PK
Person
  - id : PK

在这里我抓住了稻草-我不知道这样的事情是否可能,鉴别器可以决定父表(companyOrPerson)吗?双向工作在这里(就像我提到的,也许我应该做一些基类Contactable)?

我愿意接受有关如何做好这件事的建议。

标签: javahibernatejpa

解决方案


偏好组合而不是继承。它倾向于简化事情。

如果你有主要实体

  • 公司
  • 电子邮件

然后是几个复合材料

  • PersonEmail(包含人员和电子邮件)
  • CompanyEmail(包含公司和电子邮件)

那不符合您的需要吗?

例如

@Entity
public class Person {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;

    @OneToMany
    @JoinColumn(name="person_id")
    private List<PersonEmail> emails = new ArrayList<>();

}

@Entity
public class Company {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;

    @OneToMany()
    @JoinColumn(name="company_id")
    private List<CompanyEmail> emails = new ArrayList<>();
}

@Entity
public class Email {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;

    @javax.validation.constraints.Email
    private String email;

}

@Entity
public class PersonEmail {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="person_id",  referencedColumnName="id")
    private Person person;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="email_id",  referencedColumnName="id")
    private Email email;

}

@Entity
public class CompanyEmail
{
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="company_id",  referencedColumnName="id")
    private Company company;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="email_id",  referencedColumnName="id")
    private Email email;
}

推荐阅读