Which annotation should I use: @IdClass or @EmbeddedId
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?
Asked by: Steven519 | Posted: 23-01-2022
Answer 1
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.
Answer 2
There are three strategies to use a compound primary key:
- Mark it as
@Embeddable
and add to your entity class a normal property for it, marked with@Id
. - Add to your entity class a normal property for it, marked with
@EmbeddedId
. - Add properties to your entity class for all of its fields, mark them with
@Id
,and mark your entity class with@IdClass
, supplying the class of your primary key class.
The use of @Id
with a class marked as @Embeddable
is the most natural approach. The @Embeddable
tag can be used for non-primary key embeddable values anyway. It allows you to treat the compound primary key as a single property, and it permits the reuse of the @Embeddable
class in other tables.
The next most natural approach is the use of the @EmbeddedId
tag. Here, the primary key class cannot be used in other tables since it is not an @Embeddable
entity, but it does allow us to treat the key as a
single attribute of some class.
Finally, the use of the @IdClass
and @Id
annotations allows us to map the compound primary key class using properties of the entity itself corresponding to the names of the properties in the primary key class. The names must correspond (there is no mechanism for overriding this), and the primary key class must honor the same obligations as with the other two techniques. The only advantage to this approach is its ability to “hide†the use of the primary key class from the interface of the enclosing entity. The @IdClass
annotation takes a value parameter of Class type, which must be the class to be used as the compound primary key. The fields that correspond to the properties of the primary key class to be used must all be annotated with @Id
.
Reference: http://www.apress.com/us/book/9781430228509
Answered by: Julia875 | Posted: 24-02-2022Answer 3
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.
Answered by: Emma529 | Posted: 24-02-2022Answer 4
As far as I know, if your composite PK contains FK it's easier and more straightforward to use @IdClass
With @EmbeddedId
you have to define a mapping for your FK column twice, once in @Embeddedable
and once for as i.e. @ManyToOne
where @ManyToOne
has to be read-only(@PrimaryKeyJoinColumn
) because you can't have one column set in two variables (possible conflicts).
So you have to set your FK using a simple type in @Embeddedable
.
On the other site using @IdClass
this situation can be handled much easier as shown in Primary Keys through OneToOne and ManyToOne Relationships:
Example JPA 2.0 ManyToOne id annotation
...
@Entity
@IdClass(PhonePK.class)
public class Phone {
@Id
private String type;
@ManyToOne
@Id
@JoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
private Employee owner;
...
}
Example JPA 2.0 id class
...
public class PhonePK {
private String type;
private long owner;
public PhonePK() {}
public PhonePK(String type, long owner) {
this.type = type;
this.owner = owner;
}
public boolean equals(Object object) {
if (object instanceof PhonePK) {
PhonePK pk = (PhonePK)object;
return type.equals(pk.type) && owner == pk.owner;
} else {
return false;
}
}
public int hashCode() {
return type.hashCode() + owner;
}
}
Answered by: Rafael219 | Posted: 24-02-2022
Answer 5
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
.
Answer 6
Composite Key must not have an @Id
property when @EmbeddedId
is used.
Answer 7
With EmbeddedId you can use the IN clause in HQL, for example : FROM Entity WHERE id IN :ids
where id is an EmbeddedId whereas it's pain to achieve the same result with IdClass you will want to do something like FROM Entity WHERE idPartA = :idPartA0 AND idPartB = :idPartB0 .... OR idPartA = :idPartAN AND idPartB = :idPartBN
Similar questions
java - JPA Compound key with @EmbeddedId
In a legacy database, I have three tables: Users, Workgroups, and UsersWorkgroup. UsersWorkgroup stores what role a user has in a workgroup.
Here are the relevant code snippets:
@Entity
@Table(name = "users_workgroup")
public class UsersWorkgroup implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected UsersWorkgroupPK usersWorkgroupPK;
@JoinColumn(na...
java - Difference using @Id and @EmbeddedId for a compound key
I've created an entity that uses @Id to point to an @Embeddable compound key. Everything I believe works fine as is. However, after switching @Id to @EmbeddedId everything continues to work fine as far as I can tell.
Before:
@Entity
public final class MyEntity {
private CompoundKey id;
@Id
public CompoundKey getId() {
return id;
}
public void setId(CompoundKey ...
java - @onetoone and @EmbeddedId
I am trying to create a one-to-one relation between a class, lets call it First, and another one lets call it second.
It wont allow me to do so if the class Second uses a @EmbeddedId as its primary key, how do i get around this?
Basically the structures are as follows:
@Entity
class First {
private Integer id;
private Second second;
@OneToOne
@JoinColumn(name="id", refe...
java - Eclipse error on mapping with @EmbeddedId
I have an entity with composite key so I use the @Embeddable and @EmbeddedId annotations.
Embeddable class looks like this :
@Embeddable
public class DitaAdminAccountSkillPK implements Serializable {
@ManyToOne
@JoinColumn(name = "admin_id")
private DitaAdmin admin;
@ManyToOne
@JoinColumn(name = "account_id")
private DitaAccount account;
//constructor, getters, setters...
}
java - JPA - @EmbeddedId and @Id
This is the relevant JPA code:
@MappedSuperClass
public abstract class SuperClass {
@EmbeddedId
private FileId fileId;
protected SuperClass() {
}
public SuperClass(FileId fileId) {
this.fileId = fileId;
}
}
@Embeddable
public class FileId {
protected FileId() {
}
protected File fileName;
public FileId(File fileName) {
this.fileName = fileName;
}
}
@Entity
public MyCla...
java - @ManyToOne and @OneToOne relations with @EmbeddedId
I am trying to change the id of my database entities from a single long to a composite id consisting of two long's which are encapsulated in my ID.class shown below. What annotations would you use for ManyToOne and OneToMany relations? Did I made a mistake with my annotations, especially with @JoinColumns, @Embeddable and @EmbeddedId. My problem is that relations are stored with null;
My ID class consist of an auto...
java - How to expose @EmbeddedId converters in Spring Data REST
There are some Entities with composite Primary Keys and these entities when exposed are having incorrect Links having full qualified name of classes in URL inside _links
Also clicking on links gives such errors -
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type java.lang.String to type com.core.connection.domains.UserFriendshipId
...
java - JPA - @MapKey and @EmbeddedId
I have the following DB structure:
Where FESTIVAL_ID and LANG is composite PK and FESTIVAL_ID is FK for FESTIVAL.
In my Java code I have the following entities:
@Embeddable
public class FestivalTranslationId {
@Column(nam...
java - Hibernate @EmbeddedId
Here is my problem
IdComposite class:
@Embeddable
public class IdComposite implements Serializable{
@Column(name = "code1", nullable = false)
private String code1;
@Column(name = "code2", nullable = false)
private String code2;
// getters, setters, hashCode & equals
}
MyEntity class:
@Entity
@Table(name = "table")
public class M...
java - JPA @OneToMany with @EmbeddedId
I have the following Class (Parent):
@Entity
@Table(name = "PROBE_CUSTOMERS")
public class ProbeCustomer implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private String name;
private String hostname;
private List<ProbeMonitor> monitors;
....
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
...
Still can't find your answer? Check out these amazing Java communities for help...
Java Reddit Community | Java Help Reddit Community | Dev.to Java Community | Java Discord | Java Programmers (Facebook) | Java developers (Facebook)