JPA error - "not mapped to a single property"


#1

Hi All,

I have an Entity - ReportSection with the following structure:

@javax.persistence.Entity
@Table(name=EntityConstants.TBL_REPORT_SECTION)
@javax.persistence.Entity
@Table(name = EntityConstants.TBL_REPORT_SECTION)
public class **ReportSection** extends UpdateLockCount implements WithId {

    /** The id */
    @EmbeddedId
    private ReportSectionId id;

    @OneToMany(orphanRemoval = true, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
   @JoinColumns({ @JoinColumn(name = "TID"),
			       @JoinColumn(name = "REPORT_DEFINITION_ID"),
				@JoinColumn(name = "SECTION_NUMBER_NB")})
	private Set<TocEntry> tocEntries;
}

public class **ReportSectionId** implements Serializable {

    /** The tenant id. */
    @Column(name = "TID", precision = 10, nullable = false)
    private Integer tid;

    /** The report definition id. */
    @Column(name = "REPORT_DEFINITION_ID", precision = 10, nullable = false)
    private Long reportDefinitionId;

    /** The section number. */
    @Column(name = "SECTION_NUMBER_NB", precision = 10, nullable = false)
    private Long sectionNumber;
}

Now I am trying to join with this table from another Entity TocEntry, which has an embeddedId TocEntryId


@Entity
@Table(name = EntityConstants.TBL_SLIDE_TOC_ENTRY)
public class TocEntry extends UpdateLockCount implements WithId {

    @EmbeddedId
    private TocEntryId id;
	
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(column = @JoinColumn(name = "TID", referencedColumnName = "TID", insertable = false, updatable = false)),
            @JoinColumn(column = @JoinColumn(name = "TOC_ID", referencedColumnName = "SECTION_ID", insertable = false, updatable = false)),
           
    })
    private ReportSection sourceTocSlide;
}

public class TocEntryId implements Serializable {

    @Column(name = "TID", precision = 10, nullable = false)
    private Integer tid;

    @Column(name = "TOC_ID", precision = 10, nullable = false)
    private Long tocId;

    /** The section number. */
    @Column(name = "SLIDE_ID", precision = 10, nullable = false)
    private Long slideId;
}

In ReportSection even though the Tid and sectionId could have acted as primary keys, the system ported from legacy has the embedded composite primary key ReportSectionId with the 3 columns. However I would like the new relationships and joins to address the Tid and sectionId only. But It throws an error:

Caused by: org.hibernate.AnnotationException: referencedColumnNames(TID, SECTION_ID) of com.vermilion.vrs.jpa.entity.vpitch.TocEntry.tocEntries referencing com.vermilion.vrs.jpa.entity.reportdefinition.ReportSection not mapped to a single property
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:318)
at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1545)
… 18 more
: org.jboss.msc.service.StartException in service jboss.persistenceunit.“vrs4EAR.ear/vrs4EJB.jar#vrsJpa”: org.hibernate.AnnotationException: Unable to map collection com.vermilion.vrs.jpa.entity.reportdefinition.ReportSection.tocEntries
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:179) [wildfly-jpa-10.1.0.Final.jar:10.1.0.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:121) [wildfly-jpa-10.1.0.Final.jar:10.1.0.Final]
at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:667)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:193) [wildfly-jpa-10.1.0.Final.jar:10.1.0.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [rt.jar:1.8.0_152]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [rt.jar:1.8.0_152]
at java.lang.Thread.run(Thread.java:748) [rt.jar:1.8.0_152]
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: org.hibernate.AnnotationException: Unable to map collection com.vermilion.vrs.jpa.entity.reportdefinition.ReportSection.tocEntries
at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1555) [hibernate-core-5.0.10.Final.jar:5.0.10.Final]

Can you please point me in the right direction to address this issue of joining a non-primary key


#2

Try to replicate it with a test case. Maybe it’s a bug, but we need a test to check it out.


#3

Thanks Vlad. I was able to get get it working using the @naturalId annotation as described in your blog(https://vladmihalcea.com/the-best-way-to-map-a-many-to-many-association-with-extra-columns-when-using-jpa-and-hibernate/)
However one question is how can I get the join to be a combination of naturalId and another column from a composite primary key ?


#4

You should be able to do that via @JoinColumns as long as you set insertable and updatable to false since the associated columns are handled by the PK or @NaturalId. If that doesn’t work, it’s a bug in which case we need a test case to replicate it.