AnnotationException when @MapKey refers to a column mapped in embeddable map value

I’ve got a User entity which contains a map of UserProfiles, as you can see UserProfile is mapped as an ElementCollection, not as an individual entity.

@Entity
@Table(name = "user_")
public class User extends AbstractEntity<UserId> {

    ...

    @ElementCollection
    @CollectionTable(name = "user_profile")
    @MapKey(name = "userProfileType")
    @MapKeyEnumerated(STRING)
    private Map<UserProfileType, UserProfile> userProfiles;

}

@Embeddable
@NoArgsConstructor(access = PACKAGE)
@AllArgsConstructor(staticName = "of")
@EqualsAndHashCode
public class UserProfile {

    @Enumerated(STRING)
    private UserProfileType userProfileType;

    ...

}

Note: I’m using Hibernate 5.2.14.

Issue

When Hibernate processes these mappings, I get the following exception:

Caused by: org.hibernate.AnnotationException: Associated class not found: UserProfile
    at org.hibernate.cfg.annotations.MapBinder.bindKeyFromAssociationTable(MapBinder.java:168) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.cfg.annotations.MapBinder.access$000(MapBinder.java:66) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.cfg.annotations.MapBinder$1.secondPass(MapBinder.java:101) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:54) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1635) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1603) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:861) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:888) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:388) ~[spring-orm-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.0.4.RELEASE.jar:5.0.4.RELEASE]

Workarounds tried

I tried to use MapKeyColumn instead of MapKey, but that generates another error claiming that a physical representation of column user_profile_type already exists.

Question

I wondering if this is supposed to work according to the JPA spec?

I think it should work, because I found a very similar issue which had already been fixed in Hibernate 5: https://hibernate.atlassian.net/browse/HHH-5393

Thanks for your help!

Cheers, László

@MapKey is for associations, not basic types.

You need to add @Enumarated as well. Check out this StackOverflow answer for more details:

Thanks for your quick reply. The stackoverflow answer you are referring to is for Map<Enum, Enum>.

However, what I’m trying to persist is a Map<Enum, Embeddable> and the map’s key is also a member of the embeddable. That’s the reason I’ve used MapKey.

@MapKey is not valid. If the mapping is not supported, open a Jira issue.