java - 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(最新)中是否有可能实现这样的结构?
上面设计时的要点(是什么驱使我):
- 将所有电子邮件保存在一张表中,以进行完整性检查(唯一性)。
- 具有最小的数据库占用空间 - 上面只给出了一个表
Email
,然后是 2 个带有 2 个 FK 的连接表。 - 仍然能够保持模型设计对 Hibernate 友好(基本上不使用任何特殊查询,只使用 JPA 注释)。这意味着 Company 和 Person 都可以轻松地 LAZY 加载其特定的电子邮件(子类),并且这些子类的电子邮件可以对应于它们(
PersonEmail
toPerson
和CompanyEmail
toCompany
) - 使模型双向。
注意:我也考虑过创建类似Contactable
基类的东西,Comapny
并且Person
有Email
列表,但这不适合我的需要(每个表都没有类,也没有相同的表设计)。
我的问题是 - 有可能吗?即使我没有得到基于我给出的课程的例子的答案,只是事实会给我希望,我会找到它。
编辑 1
我是否应该在电子邮件表中使用鉴别器,然后将 FK 保留在那里?
Email
- id : PK
- email : String
- companyOrPerson : FK
- discriminator : Decides what FK points at
Company
- id : PK
Person
- id : PK
在这里我抓住了稻草-我不知道这样的事情是否可能,鉴别器可以决定父表(companyOrPerson
)吗?双向工作在这里(就像我提到的,也许我应该做一些基类Contactable
)?
我愿意接受有关如何做好这件事的建议。
解决方案
偏好组合而不是继承。它倾向于简化事情。
如果你有主要实体
- 人
- 公司
- 电子邮件
然后是几个复合材料
- 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;
}
推荐阅读
- python-3.x - 在 Facebook BlenderBot 聊天机器人中训练和测试自定义数据集
- python - 如何在 Python 中使用多个键修改嵌套字典中的一组特定值?
- python - 带有数据库值的 WTForm SelectField
- mongodb - 使用 Logstash JDBC 插件同步 MongoDB 和 Elasticsearch 时避免重复
- sql - 使用 group by 在 SQL 中查找具有特定列值的列的总和
- python - 无法使用 Watson Assistant 获取 workspace_id
- java - 使用 JAVA 中的脚本创建一个反应应用程序
- python - What is the correct way to import modules when I'm writing my own module in python?
- selenium - Testcontainers Selenium 如何更新浏览器?
- python-3.x - 我想编写一个接受数字作为字符串的代码