There are people who advocate the fact that mapping with @EmbeddedId
are more expressive and clear, because you can directly access the class that has the composite key, something that is not possible with @IdClass
. For example:
Mapping with @EmbeddedId
:
@Embeddable class EmployeeId {
String name;
LocalDate dataOfBirth;
}
@Entity class Employee {
@EmbeddedId EmployeeId employeeId;
...
}
Mapping with @IdClass
:
class EmployeeId {
String name;
LocalDate dateOfBirth;
}
@Entity class Employee {
@IdClass(EmployeeId.class);
@Id String name;
@Id LocalDate dateOfBirth;
...
}
In HQL queries, most of the time, knowing that a given field is part of a composite key and is not a simple entity field makes all the difference. That, just the @EmbeddedId
provides. Examples of queries
of both:
select e.name from Employee e //@IdClass
select e.employeeId.name from Employee e //@EmbeddedId
The second query
, at face, transmits much more information on mapping.
Another example of difference between queries
one and the other to achieve the same result, in this case using the IN
:
//com @EmbeddedId
FROM Entity WHERE id IN :ids
//com @IdClass
FROM Entity WHERE idPartA = :idPartA0 AND idPartB = :idPartB0 .... OR idPartA = :idPartAN AND idPartB = :idPartBN
On the other hand, there are very specific use cases where the @IdClass
is a much easier solution to use. For example, when one of the composite keys is also a relationship:
@Entity
@IdClass(PhonePK.class)
public class Phone {
@Id
private String type;
@ManyToOne
@Id
@JoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
private Employee owner;
...
}
public class PhonePK {
private String type;
private long owner;
...
}
In short, it is a matter of business need and code clarity that will define which mapping you will use. In practice, they both do, and quite rightly, the same thing.