Home > other >  JPA @JoinTable and @JoinColumn with composite PK not working
JPA @JoinTable and @JoinColumn with composite PK not working

Time:12-14

Hello I'm having trouble understanding the error when I do a JoinTable between 2 entities (one of them with a composite primary key).

My Entities:


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Entity
    @Table(name = "meds")
    public class Meds {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private long id;
    
        @Column
        private String name;
    
        @Column
        private BigDecimal price;
    
        @Column
        private String category;
    
        @Column
        private int pillNumber;
    
        @Column
        private Date date;
    
        @JsonIgnore
        @ManyToMany(mappedBy = "assignedMeds")
        private Set<Plans> plans = new HashSet<>();
    
    }


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Entity
    @Table(name = "plans")
    @IdClass(PlansPKId.class)
    public class Plans {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private long planId;
    
        @Id
        @Column
        private Date planDate; // format: yyyy-mm-dd
    
        @Column
        private String planName;
    
        @Column
        private String weekday;
    
        @ManyToMany
        @JoinTable(name = "Plan_Meds", joinColumns = @JoinColumn(name = "planDate", referencedColumnName = "planId"), inverseJoinColumns = @JoinColumn(name = "id"))
        private Set<Meds> assignedMeds = new HashSet<>();
    
    }

My PlansPKId class:


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public class PlansPKId implements Serializable {
    
        private long planId;
    
        private Date planDate; // format: yyyy-mm-dd
    }

and my error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Unable to map collection com.MD.Medicine.Models.Plans.assignedMeds at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.5.jar:2.7.5] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.5.jar:2.7.5] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.5.jar:2.7.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.5.jar:2.7.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.5.jar:2.7.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.5.jar:2.7.5] at com.MD.Medicine.MedicineApplication.main(MedicineApplication.java:10) ~[classes/:na] Caused by: org.hibernate.AnnotationException: Unable to map collection com.MD.Medicine.Models.Plans.assignedMeds at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1750) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1475) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:901) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:826) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:54) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1653) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1629) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:295) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1460) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1494) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.23.jar:5.3.23] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.23.jar:5.3.23] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.23.jar:5.3.23] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-5.3.23.jar:5.3.23] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.23.jar:5.3.23] ... 16 common frames omitted Caused by: org.hibernate.AnnotationException: referencedColumnNames(planId) of com.MD.Medicine.Models.Meds.assignedMeds referencing com.MD.Medicine.Models.Plans not mapped to a single property at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:203) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1740) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final] ... 32 common frames omitted

I tried @JoinColumn(name = "planDate", referencedColumnName = "planId") and also the other way around with planId first but the same thing happened. What could be wrong? Regards.

CodePudding user response:

Not interest to use a composite ID in Plans class: planId is already unique and generated by database. But that's not the issue you need to map all columns ids planDate and planId.

@ManyToMany
@JoinTable(name = "Plan_Meds", joinColumns = {
        @JoinColumn(name = "planDate", referencedColumnName = "planDate")
        @JoinColumn(name = "planId", referencedColumnName = "planId")
}, inverseJoinColumns = @JoinColumn(name = "id"))
private Set<Meds> assignedMeds = new HashSet<>();
  • Related