Error on @OneToMany relationship with Embedded fields [Referenced column '...' mapped by target property '...' occurs out of order in the list of '@JoinColumn's]

Hi all,

I’ve been working with entities that use @Embedded classes, and that need to reference each other with several properties.

In order to achieve this, I used a @OneToMany relationship and @JoinColumns annotations. And got the error:

Referenced column 'field2' mapped by target property 'embeddedEntity' occurs out of order in the list of '@JoinColumn's

I did a few experiments, to see what worked and what didn’t :

The base case :

@Table(name = "entity1")
@Entity
public class Entity1 {

    @Id
    private Long id;

    @Column
    private String field1;

    @Column
    private String field2;

    @OneToMany
    @JoinColumns({
            @JoinColumn(name = "field1", referencedColumnName = "field1", insertable = false, updatable = false),
            @JoinColumn(name = "field2", referencedColumnName = "field2", insertable = false, updatable = false),
    })
    private List<Entity2> entities2;


}
/////////////////
@Table(name = "entity2")
@Entity
public class Entity2 {

    @Id
    private Long id;

    @Column
    private String field1;

    @Column
    private String field2;

}

This does work, and permuting the @JoinColumn annotations has no negative effect.

On the other side, this :


@Table(name = "entity1")
@Entity
public class Entity1 {

    @Embeddable
    public static class EmbeddedEntity1 {

        @Column(name = "field1")
        private String field1;

        @Column(name = "field2")
        private String field2;
    }

    @Id
    private Long id;

    @Embedded
    private EmbeddedEntity1 embeddedEntity1;

    @OneToMany
    @JoinColumns({
            @JoinColumn(name = "field2", referencedColumnName = "field2", insertable = false, updatable = false),
            @JoinColumn(name = "field1", referencedColumnName = "field1", insertable = false, updatable = false),
    })
    private List<Entity2> entities2;

Doesn’t work. And I get the error :

Caused by: org.hibernate.AnnotationException: Referenced column 'field2' mapped by target property 'embeddedEntity1' occurs out of order in the list of '@JoinColumn's at org.hibernate.boot.model.internal.BinderHelper.findPropertiesByColumns(BinderHelper.java:545) at org.hibernate.boot.model.internal.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:161) at org.hibernate.boot.model.internal.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:2701) at org.hibernate.boot.model.internal.CollectionBinder.bindOneToManySecondPass(CollectionBinder.java:1701) at org.hibernate.boot.model.internal.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:1599) at org.hibernate.boot.model.internal.CollectionBinder$1.secondPass(CollectionBinder.java:1588) at org.hibernate.boot.model.internal.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:45) at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1815) at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1774) at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:332) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1432) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1503) at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1833) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782)

But if I change the EmbeddedEntity1 class to this :

    @Embeddable
    public static class EmbeddedEntity1 {

        @Column(name = "field1")
        private String z_alphabeticallyLast_field1;

        @Column(name = "field2")
        private String field2;
    }

The error disappear !

It seems like Hibernate is sorting the embedded fields by alphabetical order.

This leads to very confusing errors, since nothing indicate that the name of my fields matter, and that it could be the cause of errors !

This behavior doesn’t happen when the JOIN is a @OneToOne

Please update to the latest bug fix version. We recently fixed this problem: [HHH-17964] - Hibernate JIRA