簡體   English   中英

JPA Hibernate刪除實體的子對象,與雙PK連接觸發SQL更新而不是刪除?

[英]JPA Hibernate remove child object of entity, connected with dual PK triggers SQL update instead of delete?

我有以下表結構:

在此處輸入圖片說明

  • 每個 chat_bot 可以有多個版本。
  • 每個版本都可以部署到環境中。
  • 版本具有雙主鍵,其中之一是從 chat_bot 表中引用的。
  • 環境表只有主鍵。 其中兩個是從版本表中引用的。

我有以下類結構:

@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 連接的子元素?

您的映射中有一些錯誤。

  1. 加入列總是在子端

     @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true) @JoinColumns({ @JoinColumn(name = "botId", referencedColumnName = "botId"), @JoinColumn(name = "version", referencedColumnName = "version") }) private Set<BotEnvironments> environments = new LinkedHashSet<>();

此映射應移至子項 ( BotEnvironments )。

  1. mappedBy應該指向與實體相同類型的字段。 您已經定義了mappedBy = "botId" ,但botIdString類型(它是一個外鍵)。 這不會映射實體之間的關系。

  2. 不要害怕雙向關系。 它們不會造成性能開銷——實際上很多時候它們可以優化持久性性能。

我糾正了其他一些小問題。 為簡潔起見,我省略了 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM