What is the difference between Embeddedid and Idclass in Hibernate?

Asked

Viewed 4,147 times

6

I have read in the Hibernate 5.0 documentation that you can implement composite primary keys using two ways.

The first of these is using the annotation @IdClass and imitating the Idclass attributes in the original class.

The other is using the annotation @EmbeddedId, where you can create an inner/nested class and include a reference to it in the original class.

Is there any major difference between the two forms?

2 answers

9


Are two ways to make the representation of the composite key in the entity.

Let’s say you have a table parametro, entity Parametro and its composite key is nome and empresa. The table can be as the example below:

name enterprise value
rate 56 3.44

The @EmbeddedId creates an abstraction within the entity that does not exist in the database table. It unites the information that makes up the composite key under the same variable. See, respectively, the class representing the composite key and the entity mapping it with @EmbeddedId:

 @Embeddable
 class ParametroId {
      private String nome;
      private Integer empresa;
 }

 @Entity
 class Parametro {
      @EmbeddedId
      private ParametroId parametroId;
 }

See now that this mapping format is reflected in the queries. Example in JPQL:

SELECT p FROM Parametro p where p.parametroId = :parametroId

Analyzing the above query, note that there is no column parametroId on the table parametro of the database, which can be a little strange when making queries in JPQL, where one of its advantages is to be similar to SQL. And if you’re going to make an appointment just for nome or empresa, the discrepancy between the generated SQL and JPQL is even more evident. See:

SELECT p FROM Parametro p where p.parametroId.empresa = :empresa

Already the @IdClass does not involve creating a new class with the table keys. Thus, queries are closer to the generated SQL:

SELECT p FROM Parametro p where p.nome = :nome AND p.empresa = :empresa;

However, this flexibility makes the concept of "composite key" hidden in the code. With @EmbeddedId the use of the composite key ends up being more natural in the code, especially if using the CrudRepository of Spring, where to use the @IdClass you needs to simulate a class @EmbeddedId.

5

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.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.