Which annotation should I use: @IdClass or @EmbeddedId

Viewed 110347

The JPA (Java Persistence API) specification has 2 different ways to specify entity composite keys: @IdClass and @EmbeddedId.

I'm using both annotations on my mapped entities, but it turns out to be a big mess to people who aren't very familiar with JPA.

I want to adopt only one way to specify composite keys. Which one is really the best? Why?

7 Answers

I consider that @EmbeddedId is probably more verbose because with @IdClass you cannot access the entire primary key object using any field access operator. Using the @EmbeddedId you can do like this:

@Embeddable class EmployeeId { name, dataOfBirth }
@Entity class Employee {
  @EmbeddedId EmployeeId employeeId;
  ...
}

This gives a clear notion of the fields that make the composite key because they are all aggregated in a class that is accessed trough a field access operator.

Another difference with @IdClass and @EmbeddedId is when it comes to write HQL :

With @IdClass you write:

select e.name from Employee e

and with @EmbeddedId you have to write:

select e.employeeId.name from Employee e

You have to write more text for the same query. Some may argue that this differs from a more natural language like the one promoted by IdClass. But most of the times understanding right from the query that a given field is part of the composite key is of invaluable help.

I discovered an instance where I had to use EmbeddedId instead of IdClass. In this scenario there is a join table that has additional columns defined. I attempted to solve this problem using IdClass to represent the key of an entity that explicitly represents rows in the join table. I couldn't get it working this way. Thankfully "Java Persistence With Hibernate" has a section dedicated to this topic. One proposed solution was very similar to mine but it used EmbeddedId instead. I modeled my objects after those in the book it now behaves correctly.

I think the main advantage is that we could use @GeneratedValue for the id when using the @IdClass? I'm sure we can't use @GeneratedValue for @EmbeddedId.

Related