Home > Back-end >  Hibernate creates wrong table relations in MySQL
Hibernate creates wrong table relations in MySQL

Time:12-01

I have a problem with Hibernate. I am using Spring 2.7.5. I have three entities.

  • Alarm,
  • AlarmList,
  • ListAlarmJoinTable.

Alarm and AlarmList are in a MtoM relation. The tricky part is that they are not referencing each other, but they both have a OneToMany reference to the ListAlarmJoinTable.

Here are the classes:

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "alarm")
public class Alarm {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Integer alarmId;

    @Column(unique = true)
    String name;
    private Long time;
    private Integer code;
    private Integer priority;
    private String source;
    private String description;
    private String codeAsAsString;
    private String priorityAsString;
    private Integer dmId;
    private Boolean internal;
    private Integer instnaceindex;

    @OneToMany(orphanRemoval = true, cascade = {CascadeType.REMOVE, CascadeType.MERGE})
    private List<ListAlarmJoinTable> alarmLists;

    @Override
    public String toString() {
        return "JsonAlarm [time="   time   ", code="   code   ", priority="
                  priority   ", source="   source   ", description="
                  description   ", alarmId="   alarmId   ", codeAsAsString="
                  codeAsAsString   ", priorityAsString="   priorityAsString
                  ", dmId="   dmId   ", internal="   internal
                  ", instnaceindex="   instnaceindex   "]";
    }
}
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
@Table(name = "alarm_list")
public class AlarmList {

    @Id
    private String name;

    @OneToMany(orphanRemoval = true, cascade = {CascadeType.REMOVE, CascadeType.MERGE})
    private List<ListSequenceJoinTable> alarmSequences;

    @OneToMany(orphanRemoval = true, cascade = {CascadeType.REMOVE, CascadeType.MERGE})
    private List<ListAlarmJoinTable> alarms;

}
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Table(name = "list_alarms_join_table")
public class ListAlarmJoinTable {

    @EmbeddedId
    private AlarmListId id;
    private int position;

}
@Embeddable
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class AlarmListId implements Serializable {

    private Integer alarmId;
    private String listId;

}

When Hibernate creates the schema and tables, it creates the following tables:

"alarm", "alarm_list", "alarm_alarm_lists" , "alarm_list_alarms", "list_alarms_join_table".

What I actually need are these: "alarm", "alarm_list", "list_alarms_join_table". Now, at first I thought it was the dialect, so I tried out every MySQL dialect and it didn't work. I even ran maven clean install (even though I knew that wouldn't change anything).

For further information this is my application.properties:

enter image description here

CodePudding user response:

The mapping is wrong because JPA cannot guess that ListAlarmJoinTable is essentially a join table (with an extra property). JPA sees your setup and thinks the relations AlarmAlarmListId and AlarmListAlarmListId have nothing to do with the fields of the AlarmListId, that you intended to be foreign keys.

Change the AlarmListId as follows to make the relation explicit:

@Embeddable
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class AlarmListId implements Serializable {
    @ManyToOne(optional=false, fetch=LAZY)
    private Alarm alarm;
    @ManyToOne(optional=false, fetch=LAZY)
    private AlarmList list;

    // You MUST implement hashCode() and equals(), probably Lombok's
    // @EqualsAndHashCode is enough but please check the semantics!!!
}

Now, you have to use mappedBy in the @OneToMany annotations over Alarm.alarmLists and AlarmList.alarms. I think the value should be:

    @OneToMany(..., mappedBy = "id.alarm")
    private List<ListAlarmJoinTable> alarmLists;

    // AND:

    @OneToMany(..., mappedBy = "id.list")
    private List<ListAlarmJoinTable> alarms;

The mappedBy property will help JPA understand that these are just the reverse sides of the same relation.

  • Related