Having the following entities:
@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;
}
A Discipline
is for a specific Employee
. An Employee
may have 0 to several disciplines. A discipline is for only one Employee
, no more no less. In the Discipline
world (micro-service), it requires only a few attributes from the full Employee
class (id, firstName and lastName). In the Employee
World (micro-service), all Employee
fields are relevant.
How do I properly set my relation between both entities without fetching the Employee
entity for each Discipline
but only the required fields as I would do with a projection?
Must I refactor my Employee
entity by extracting a superclass with only the attributes' subset?
In a magical world, I would like to have Discipline
entity defines as follow:
@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();
}
Where EmployeeProfile
here should look similar to what a Spring Data JPA interface based projection would use.
Aimed goals by doing this:
addDiscipline
request to fail due to an outdated employee instance on an irrelevant attribute. This could happen if we link Discipline
to the full `Employee Thanks to @crizzis who proposed what I was looking for. Here's the solution if anybody else is looking for this in future.
SOLUTION: Simply have two entities, one with all the attributes and another one with only the subset you're interested in and have both entities using same table as follow:
@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;
}
Than you can have link other entities on this EmployeeProfile
class as follow:
@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;
}
As by default on ManyToOne
relationship no operations are cascaded, this suits perfectly our needs.
@AlanHay proposed to go down the REST way by having a REST endpoint returning this specific DTO. It is another great solution especially in a micro-service architecture.
As in our case, all our entities are still persisted in the same DB, we are going with the above solution as first step of doing micro-services is to build a great/decoupled monolithic application and because it will handle everything in only one DB query. And when the day come to split Discipline
and Employee
in different micro-services, it will be very simple to do so as Discipline table hold only the employee id, avoiding painful DB migration.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.