具有以下实体:
@Entity
@Table
public class Employee {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
@NotBlank
private String firstName;
@NotBlank
private String lastName;
private Gender gender;
private Instant birthDate;
private String email;
private String corporateEmail;
@Embedded
private Address address;
// and many more
// + all getters and setters
}
@Entity
@Table
public class Discipline {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
@NotNull
private Instant date;
private String infraction;
}
Discipline
用于特定的Employee
。 Employee
可以具有0到几个学科。一门学科只适用于一个Employee
,且不少于。在Discipline
世界(微服务)中,它只需要完整Employee
类中的一些属性(id,firstName和lastName)。在Employee
世界(微服务)中,所有Employee
字段都是相关的。
如何在不为每个Employee
提取Discipline
实体的情况下正确设置两个实体之间的关系,而只像投影一样提取必填字段?
我是否必须通过提取仅包含属性子集的超类来重构Employee
实体?
在一个神奇的世界中,我希望Discipline
实体定义如下:
@Entity
@Table
public class Discipline {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
@NotNull
private Instant date;
private String infraction;
@ManyToOne
private EmployeeProfile employeeProfile;
}
public interface EmployeeProfile {
UUID getId();
String getFirstName();
String getLastName();
}
EmployeeProfile
的位置应类似于基于Spring Data JPA接口的投影所使用的位置。
这样做可以达到目标:
addDiscipline
请求失败。如果我们将Discipline
链接到完整的`Employee 答案 0 :(得分:0)
感谢@crizzis提出了我想要的东西。如果将来还有其他人在寻找,这就是解决方案。
解决方案: 只需有两个实体,一个具有所有属性,另一个具有仅您感兴趣的子集,并且两个实体都使用相同的表,如下所示:
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
@NotBlank
private String firstName;
@NotBlank
private String lastName;
private Gender gender;
private Instant birthDate;
private String email;
private String corporateEmail;
@Embedded
private Address address;
...
}
@Entity
@Table(name = "EMPLOYEE")
@Immutable
public class EmployeeProfile {
@Id
private UUID id;
private String firstName;
private String lastName;
}
相比之下,您可以在此EmployeeProfile
类上链接其他实体,
@Entity
@Table
public class Discipline {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
@NotNull
private Instant date;
private String infraction;
@ManyToOne
@JoinColumn(name = "employee_id")
private EmployeeProfile employeeProfile;
}
默认情况下,ManyToOne
关系中没有级联操作,因此完全符合我们的需求。
@AlanHay建议通过让REST端点返回此特定的DTO来实现REST方式。这是另一个很棒的解决方案,尤其是在微服务架构中。
在本例中,我们所有的实体仍然保留在同一个数据库中,我们采用上述解决方案,因为进行微服务的第一步是构建一个出色的/解耦的整体应用程序,因为它将处理所有只有一个数据库查询。而且当将Discipline
和Employee
拆分为不同的微服务的日子时,这样做非常简单,因为Discipline表仅保留员工ID,从而避免了痛苦的DB迁移。