В вашем отображении есть некоторые ошибки.
Объединяющиеся столбцы всегда на дочерней стороне :
@OneToMany(fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumns({
@JoinColumn(name = "botId", referencedColumnName = "botId"),
@JoinColumn(name = "version", referencedColumnName = "version")
})
private Set<BotEnvironments> environments = new LinkedHashSet<>();
Это отображение должно быть перенесено на ребенка (BotEnvironments
).
mappedBy
должен указывать на поле того же типа, что и объект. Вы определили mappedBy = "botId"
, но botId
имеет тип String
(это внешний ключ). Это не отобразит отношения между сущностями.
Не бойтесь двунаправленных отношений. Они не приводят к снижению производительности - на самом деле очень часто они могут оптимизировать постоянство производительности.
Была пара других мелких вещей, которые я исправил. Я пропустил аннотации Lombok и выборку типа для краткости. Вот правильное отображение (сгенерированная схема базы данных одинакова):
Bot :
@Entity
@Table(name = "chat_bot")
public class Bot {
@Id
private String id;
@OneToMany(mappedBy = "bot", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<BotVersion> versions = new LinkedHashSet<>();
}
BotVersion :
@Entity
@Table(name = "chat_bot_version")
@IdClass(BotVersionPK.class)
public class BotVersion {
@Id
private String botId;
@Id
private int version;
@ManyToOne
@JoinColumn(name = "botId", insertable=false, updatable=false)
private Bot bot;
@Type(type = "text")
private String json;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "botVersion")
private Set<BotEnvironments> environments = new LinkedHashSet<>();
}
BotEnvironments :
@Entity
@Table(name = "chat_bot_environments")
@IdClass(BotEnvironmentsPK.class)
public class BotEnvironments {
@Id
private String botId;
@Id
private int version;
@Id
private String environmentCode;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "botId", referencedColumnName = "botId", insertable=false, updatable=false),
@JoinColumn(name = "version", referencedColumnName = "version", insertable=false, updatable=false)
})
private BotVersion botVersion;
}
Идентификационные классы не изменены.
Вот простой тест, который проверяет, работает ли он:
@Test
public void test() {
// given
BotEnvironments botEnvironments = new BotEnvironments("bid", 1, "env");
BotEnvironments botEnvironments1 = new BotEnvironments("bid", 1, "env1");
BotVersion botVersion = new BotVersion("bid", 1, "json", Set.of(botEnvironments, botEnvironments1));
Bot bot = new Bot("bid", Set.of(botVersion));
botRepository.save(bot);
// when
Bot savedBot = botRepository.findAll().get(0);
savedBot.getVersions().iterator().next().getEnvironments().remove(savedBot.getVersions().iterator().next().getEnvironments().iterator().next());
botRepository.save(savedBot);
// then
assertEquals(1, botEnvironmentsRepository.findAll().size());
}