Search code examples
javaspringdatabasejparelational-database

JPA cannot change column used in foreign key constraint


I have strange database structure where I have a pair of 2 foreign keys as primary key in 1 table. In another table I have 3 foreign keys and as a primary key and I struggle to make that as a JPA entity class. The error I get is: Cannot change column 'workstep_no': used in a foreign key constraint 'fk_order_has_workstep_workstep'

Here is the db Schema: db schema Here are some of my entity classes OrderHasWorkstep

@Entity
@Table(name = "order_has_workstep", indexes = {
        @Index(name = "fk_order_has_workstep_order_idx", columnList = "order_order_no"),
        @Index(name = "fk_order_has_workstep_workstep_idx", columnList = "workstep_workstep_no, workstep_article_article_no"),
        @Index(name = "fk_order_has_workstep_machine_idx", columnList = "machine_machine_no")
})
public class OrderHasWorkstep {
    @EmbeddedId
    private OrderHasWorkstepId id;

    @MapsId("orderOrderNo")
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "order_order_no", nullable = false)
    private Order orderOrderNo;

    @MapsId("id")
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumns({
            @JoinColumn(name = "workstep_workstep_no", referencedColumnName = "workstep_no", nullable = false),
            @JoinColumn(name = "workstep_article_article_no", referencedColumnName = "article_article_no", nullable = false)
    })
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Workstep workstep;

    @ManyToOne(fetch = FetchType.LAZY)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "machine_machine_no")
    private Machine machineMachineNo;

    @Column(name = "planned_calendar_week", length = 7)
    private String plannedCalendarWeek;

    @Column(name = "starting_date", length = 7)
    private String startingDate;

    @Column(name = "ending_date", length = 7)
    private String endingDate;

    @Column(name = "status")
    private Integer status;
// getters and setters

OrderHasWorkstepId:

@Embeddable
public class OrderHasWorkstepId implements Serializable {
    private static final long serialVersionUID = -488175951625341581L;
    @Column(name = "order_order_no", nullable = false, length = 10)
    private String orderOrderNo;

    @Column(name = "workstep_workstep_no", nullable = false, length = 3)
    private String workstepWorkstepNo;

    @Column(name = "workstep_article_article_no", nullable = false, length = 45)
    private String workstepArticleArticleNo;
//getters setters hashcode equals

Workstep:

@Entity
@Table(name = "workstep", indexes = {
        @Index(name = "fk_workstep_article_idx", columnList = "article_article_no")
})
public class Workstep {
    @EmbeddedId
    private WorkstepId id;

    @MapsId("articleArticleNo")
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "article_article_no", nullable = false)
    private Article articleArticleNo;

    @Lob
    @Column(name = "description")
    private String description;

    @Column(name = "setup_time")
    private LocalTime setupTime;

    @Column(name = "run_time")
    private LocalTime runTime;

    @Column(name = "machine_group", length = 5)
    private String machineGroup;
//getters setters

WorkstepId

@Embeddable
public class WorkstepId implements Serializable {
    private static final long serialVersionUID = 2987311413950947398L;
    @Column(name = "workstep_no", nullable = false, length = 3)
    private String workstepNo;

    @Column(name = "article_article_no", nullable = false, length = 45)
    private String articleArticleNo;

I tried to restructure the WorkstepIds to use entities not just strings but it still didnt work. I assume it could be something to do with the pair of columns as primary key taken into order_has_workstep


Solution

  • Try more simply:

    @Entity
    @Table(name = "order_has_workstep", indexes = {
            @Index(name = "fk_order_has_workstep_order_idx", columnList = "order_order_no"),
            @Index(name = "fk_order_has_workstep_workstep_idx", columnList = "workstep_workstep_no, workstep_article_article_no"),
            @Index(name = "fk_order_has_workstep_machine_idx", columnList = "machine_machine_no")
    })
    @IdClass(OrderHasWorkstepId.class)
    public class OrderHasWorkstep {
    
        @Id
        @ManyToOne(fetch = FetchType.LAZY, optional = false)
        @OnDelete(action = OnDeleteAction.CASCADE)
        @JoinColumn(name = "order_order_no", nullable = false)
        private Order orderOrderNo;
    
        @Id
        @ManyToOne(fetch = FetchType.LAZY, optional = false)
        @JoinColumns({
                @JoinColumn(name = "workstep_workstep_no", referencedColumnName = "workstep_no", nullable = false),
                @JoinColumn(name = "workstep_article_article_no", referencedColumnName = "article_article_no", nullable = false)
        })
        @OnDelete(action = OnDeleteAction.CASCADE)
        private Workstep workstep;
      ..
    }
    
    
    public class OrderHasWorkstepId implements Serializable {
        private static final long serialVersionUID = -488175951625341581L;
    
        private String orderOrderNo;
        private WorkstepId workstep;
        ..
    }
    

    With JPA derived IDs, the referenced entity's ID must be used as is in the ID class, and named the same as the ID property.