Getting Unable to find column with logical name error when I refer to composite key

Viewed 81

I've see this question in several posts here. But found non of them helped me to fix it. And unable to track on why this exception is happening.

Here are my entities

@Entity
@Table(name = "iiot_machine")
public class IIOTMachineModel {

   @Id
   @Column(name = "machine_id")
   private String machineId;

   @Column(name = "machine_name")
   private String machineName;

   @Column(name = "machine_description")
   private String machineDescription;

   @Column(name="created_on", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
   private LocalDateTime createdOn;

   <-- Setters and Getters -->
}

Second Entity with Composite Entity with Composite Key as follow

@Entity
@Table(name = "iiot_shift")
public class IIOTShiftModel implements Serializable {

   private static final long serialVersionUID = 1L;

   @Id
   @Column(name = "shift_id")
   private String shiftId;

   @Id
   @ManyToOne
   @JoinColumn(name="machine_id", referencedColumnName = "machine_id")
   private IIOTMachineModel machine;

   @JsonFormat(shape = Shape.STRING, pattern = "HH:mm:ss")
   @Column(name = "start_time")
   private LocalTime startTime;

   @JsonFormat(shape = Shape.STRING, pattern = "HH:mm:ss")
   @Column(name = "end_time")
   private LocalTime endTime;
    
   @Column(name= "created_on", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
   private LocalDateTime createdOn;

   <-- Setters and Getters -->
}

So far, with these two above entities, when I run the application, everything works fine. But when I add below entity which has One-to-May Relation ship with shift, I'm getting an error. Entity is defined below

@Entity
@Table(name="iiot_product")
public class IIOTProductModel implements Serializable {

   private static final long serialVersionUID = 7807669404047523909L;

   @Id
   @Column(name = "product_id", length = 100)
   private String productId;

   @Id
   @ManyToOne
   @JoinColumn(name="machine_id", referencedColumnName = "machine_id")
   private IIOTMachineModel machine;

   @Column(name = "line_id")
   private String lineId;

   private String variant;

   @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
   @JoinColumns({
       @JoinColumn(name="shift_id", referencedColumnName="shift_id"),
       @JoinColumn(name="machine_id", referencedColumnName="machine_id")
   })
   private IIOTShiftModel shift;
   private String operatorName;

   <-- Setters and Getters -->
}

Here with this Entity, particularly when I'm mapping shift with two keys, I'm getting this error. Please let me know if I'm missing something in here.

Full Stack Trace as follows

2020-07-16 15:45:20.436  WARN 21496 --- [  restartedMain] 
o.s.b.f.support.DisposableBeanAdapter    : Invocation of destroy method 
failed on bean with name 'entityManagerFactory': 
org.hibernate.MappingException: Unable to find column with logical name: 
machine_id in iiot_shift
2020-07-16 15:45:20.436  INFO 21496 --- [  restartedMain] 
o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 
'applicationTaskExecutor'
2020-07-16 15:45:20.437  INFO 21496 --- [  restartedMain] 
com.zaxxer.hikari.HikariDataSource       : HikariPool-64 - Shutdown 
initiated...
2020-07-16 15:45:20.450  INFO 21496 --- [  restartedMain] 
com.zaxxer.hikari.HikariDataSource       : HikariPool-64 - Shutdown 
completed.
2020-07-16 15:45:20.576  INFO 21496 --- [  restartedMain] 
o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
1 Answers
  • You need two primary key classes
   public class IIOTShiftModelPK  implements Serializable {
     private String machine;

     private String shiftId;

     .....getters and setters
}
   public class IIOTProductModelPK  implements Serializable {
     private String productId;
     private String machine;

     ..getters and setters
   }
  • Use the primary key classes
    @Entity
    @Table(name="iiot_product")
    @IdClass(IIOTProductModelPK.class)
    public class IIOTProductModel implements Serializable {
    @Entity
    @Table(name = "iiot_shift")
    @IdClass(IIOTShiftModelPK.class)
    public class IIOTShiftModel implements Serializable {
  • Updated product model as primary key is used part of join to another relationship
    @Column(name = "shift_id")
    private String shiftId;

    @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name="shift_id", referencedColumnName="shift_id",
                        insertable = false, updatable = false),
            @JoinColumn(name="machine_id", referencedColumnName="machine_id", 
                        insertable = false, updatable = false)
    })
    private IIOTShiftModel shift;

    public IIOTProductModel(String productId, IIOTMachineModel machine, 
                            String lineId, String variant, 
                            IIOTShiftModel shift, 
                            String operatorName) {
        this.productId = productId;
        this.machine = machine;
        this.lineId = lineId;
        this.variant = variant;
        this.shift = shift;
        this.operatorName = operatorName;
        if (Objects.nonNull(shift))
            this.shiftId = shift.getShiftId();
    }

    public void setShift(IIOTShiftModel shift) {
        this.shift = shift;
        this.shiftId = shift.getShiftId();
    }
Related