[英]JPA Hibernate remove child object of entity, connected with dual PK triggers SQL update instead of delete?
我有以下表結構:
我有以下類結構:
@Entity
@AllArgsConstructor
@Table(name = "chat_bot")
@NoArgsConstructor
public class Bot {
@Id
private String id;
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(mappedBy = "botId", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<BotVersion> versions = new LinkedHashSet<>();
}
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class BotVersionPK implements Serializable {
private String botId;
private int version;
}
@Entity
@AllArgsConstructor
@Table(name = "chat_bot_version")
@NoArgsConstructor
@IdClass(BotVersionPK.class)
public class BotVersion {
@Id
private String botId;
@Id
private int version;
@Type(type = "text")
private String json;
@OneToMany(fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumns({
@JoinColumn(name = "botId", referencedColumnName = "botId"),
@JoinColumn(name = "version", referencedColumnName = "version")
})
private Set<BotEnvironments> environments = new LinkedHashSet<>();
}
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class BotEnvironmentsPK implements Serializable {
private String botId;
private int version;
private String environmentCode;
}
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "chat_bot_environments")
@IdClass(BotEnvironmentsPK.class)
public class BotEnvironments {
@Id
private String botId;
@Id
private int version;
@Id
private String environmentCode;
}
我使用 JpaRepository< Bot, String > 來加載和保存信息。
問題:如果我從“環境”集中刪除一個項目並保留它,Hibernate 不會觸發 DELETE 操作,而是觸發 UPDATE 操作:
update chat_bot_environments set bot_id=null, version=null where bot_id=? and version=?
我收到以下錯誤,這是有效的:
Column 'bot_id' cannot be null
為什么 Hibernate JPA 觸發更新而不是 DELETE? 如何刪除由非空 PK 連接的子元素?
您的映射中有一些錯誤。
加入列總是在子端:
@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 注釋和獲取類型。 這是正確的映射(生成的數據庫架構是相同的):
機器人:
@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<>();
}
機器人版本:
@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<>();
}
機器人環境:
@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;
}
Id 類不變。
這是一個簡單的測試,檢查它是否有效:
@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());
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.