There are people who advocate the fact that mappings with @EmbeddedId
are more expressive and clear because you can directly access the class that has the compound 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 particular field is part of a compound key and is not a simple field of the entity makes all the difference. That, only @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
, of course, conveys much more information about the mapping.
Another example of a difference between queries
of one and another 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 @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's a matter of business need and code clarity that will define which mapping you're going to use. In practice, both do, and very well, the same thing.