Is it possible to retrieve @IdClass from Metamodel?

I have some entities that have a composite primary key and are annotated with:

@IdClass(PrimaryKeyClass.class)

This is how I currently retrieve the @IdClass class:

EntityType<?> entityType = entityManager.getMetamodel().entity(entityClass);
Class<?> result = entityType.getJavaType().getAnnotation(IdClass.class).value();

My question is if it possible to retrieve @IdClass of given entity directly from the Metamodel. I seem to be able to retrieve the individual fields that are part of the primary key and annotated with @Id, but not the PK class.

Alternatively, do you see any problem with my current approach?

Cheers

entityType.getIdType().getJavaType() should return what you are looking for.

Thank you for response.

This is what I initially tried, but I receive null for entityType.getIdType().

Please note that I did not use annotate the field with @EmbeddedId, but added the annotation @IdClass(…) on the entity class and kept the fields that compose the key in the class. With the embeddable approach it would have worked.

Ok, in that case you can access this through entityType.getAttribute("id").getBindableJavaType()

That also does not work for me. “id” is not part of the attributes of the entity type, which makes sense to me since it is not a field in the entity class.

Just to be sure, this is my entity:

public class PrimaryKeyClass implements Serializable {
private Long first;
private Short second;

// + getters/setters
}
@Entity
@IdClass(PrimaryKeyClass.class)
@MappedSuperclass
public class MyEntity implements Serializable {
@Id
private Long first;

@Id
private Short second;

// + other fields/getters/setters
}

Also, it is not really important because of my previous point, but entityType.getAttribute("id") returns an Attribute that does not implement getBindableJavaType(). Available methods: getDeclaringType(), getJavaMember(), getJavaType(), getName(), getPersistentAttributeType(), isAssociation(), isCollection().

We treat id as a “special” attribute name in case you don’t have an attribute named like that. You could also use the {id} name instead if you fancy that more.

Also, it is not really important because of my previous point, but entityType.getAttribute("id") returns an Attribute that does not implement getBindableJavaType().

Well, I don’t have the code in front of me, so I’m just giving you advice based on memory. getJavaType() should return what you are looking for then though.

You could also use the {id} name instead if you fancy that more.

I’m trying to obtain the @IdClass containing these @Id annotated fields. These would be the PK of entity, but not an actual field in the class.

I debugged the Hibernate code. And my findings these thing happen in the following order:

(in org.hibernate.cfg.AnnotationBinder)

1/ the annotation @IdClass is read
2/ the @Id attributes are saved
3/ boolean isIdClass is calculated
4/ … (the @IdClass type is not saved)

Therefore I question whether it is possible to return in any way the type of the PK since Hibernate seems to work only with this set of fields annotated with @Id and not the Java type of the PK (the manual here seems to suggest the same: HIBERNATE - Relational Persistence for Idiomatic Java)

Which Hibernate version are you using? Some of the things I talk about here depend on that.

You could also use the {id} name instead if you fancy that more.

Sorry for the confusion. First of all, the {id} name is actually just an internal name used for the runtime mapping model, not for the JPA model. I wrongly assumed this was accessible in the JPA metamodel as well.

Since Hibernate 6, there are JPA metamodel extensions which you can use to query this information.

((IdentifiableDomainType<?>) entityManager.getMetamodel().entity(entityClass))
  .getIdentifierDescriptor()
  .getSqmPathType()
  .getJavaType()

Will give you that information. If you don’t want to use that or are still stuck on Hibernate 5, it’s probably best to keep using what you have right now.

1 Like

Yes, I have Hibernate version 5.4.22.

Then that makes sense. Thanks for the help.