自動処理[JPA]ソフトdelete
データを削除する方法は
JPAの実装チェーンHypernetには、次の2つの機能があります.
1)削除時にdeleteクエリではなく他の構文を実行する
2)あるエンティティをクエリーするすべてのクエリーにwhere条件を追加する機能
これにより、soft delete処理と削除されていないデータのクエリーを簡素化できます.
次に、エンティティの例を示します.初期作成時にデフォルト値falseを削除するかどうか.
削除ロジックを実行する場合は、updateクエリを使用してdeleteクエリではなく、削除したフィールド値をtrueに変更する必要があります.この場合、
@SQLDeleteは、deleteクエリではなく、エンティティの削除時に実行されるCustomsql文を表す構文です.
ソフトウェアdeleteを処理すると、クエリー要求時に削除されていないデータしかインポートできません.この場合、
デフォルトでは、@Where宣言は適用されるwhere構文を表します.通常ソフトウェアdeleteを行うために使用されます.
ソフトウェアdeleteを処理するエンティティは、継承関係である場合があります.
下図に示すように、各サブクラスに対して https://www.baeldung.com/spring-jpa-soft-delete https://steady-coding.tistory.com/579#%EA%B3%84%EC%B8%B5%ED%98%95_%EC%97%94%ED%8B%B0%ED%8B%B0%EC%97%90%EC%84%9C_%EC%A3%BC%EC%9D%98%ED%95%A0_%EC%A0%90
hard delete
とsoft delete
2種類あります.hard delete
は、クエリを削除することによってデータベースから実際に削除する方法である.soft delete
は、実際にはデータベースからデータを削除するのではなく、テーブルに「削除」(Deleted)などのフィールドを追加し、クエリーを更新することで削除値を変更します.soft delete
の場合、クエリ結果の削除値を返すべきではありません.したがって、where deleted = false
などの条件を追加するか、アプリケーション側が削除していないデータのみをフィルタする必要があります.ただし、各クエリーロジックに直接条件を追加すると、漏れてしまう可能性があります.JPAの実装チェーンHypernetには、次の2つの機能があります.
1)削除時にdeleteクエリではなく他の構文を実行する
2)あるエンティティをクエリーするすべてのクエリーにwhere条件を追加する機能
これにより、soft delete処理と削除されていないデータのクエリーを簡素化できます.
例
次に、エンティティの例を示します.初期作成時にデフォルト値falseを削除するかどうか.
@Entity
public class Shop {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String address;
private boolean deleted = Boolean.FALSE; // 삭제 여부 기본값 false
}
元のファイルを削除しようとすると、次のように処理されます.delete呼び出し後にfindByIdとして削除したShopをクエリーしようとすると、実際のデータベースに格納されている値が削除されたため、optionalは空になります. @Test
@DisplayName("Shop soft delete")
public void delete() {
Shop shop = new Shop("가게이름", "대구광역시");
Shop savedShop = shopRepository.save(shop);
assertThat(savedShop.getId()).isNotNull();
assertThat(savedShop.isDeleted()).isFalse();
shopRepository.delete(savedShop);
entityManager.flush();
Optional<Shop> afterDelete = shopRepository.findById(savedShop.getId());
assertThat(afterDelete).isEmpty();
}
deleteクエリの発生も表示されます. delete
from
shop
where
id=?
@SQLDelete
削除ロジックを実行する場合は、updateクエリを使用してdeleteクエリではなく、削除したフィールド値をtrueに変更する必要があります.この場合、
@SQLDelete
を使用することができる.@SQLDeleteは、deleteクエリではなく、エンティティの削除時に実行されるCustomsql文を表す構文です.
@SQLDelete
に書き込まれると、deleteクエリではなくエンティティの削除を要求するときに更新クエリが実行されます.@Entity
@SQLDelete(sql = "UPDATE shop SET deleted = true WHERE id = ?")
public class Shop {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String address;
private boolean deleted = Boolean.FALSE; // 삭제 여부 기본값 false
}
さっきやったテストを実行しましょう.実際に削除されていないため、optionalは空ではなく、削除値がtrueに変更されていることがわかります. @Test
@DisplayName("Shop soft delete")
public void delete() {
Shop shop = new Shop("가게이름", "대구광역시");
Shop savedShop = shopRepository.save(shop);
assertThat(savedShop.getId()).isNotNull();
assertThat(savedShop.isDeleted()).isFalse();
shopRepository.delete(savedShop);
entityManager.flush();
Optional<Shop> afterDelete = shopRepository.findById(savedShop.getId());
assertThat(afterDelete).isNotEmpty();
assertThat(afterDelete.get().isDeleted()).isTrue();
}
また、更新クエリーが発生していることもわかります. UPDATE
shop
SET
deleted = true
WHERE
id = ?
*SQLDeleteは、永続性コンテキストで管理され、トランザクションが完了した後に実際のデータベースにクエリーが送信されたときに処理されます.@Where
ソフトウェアdeleteを処理すると、クエリー要求時に削除されていないデータしかインポートできません.この場合、
@Where
を使用することができる.デフォルトでは、@Where宣言は適用されるwhere構文を表します.通常ソフトウェアdeleteを行うために使用されます.
@SQLDelete
と同様に、エンティティに書き込むだけです.これはdefaultオプションとして、このエンティティをクエリーするすべてのリクエストに適用されます.@Entity
@SQLDelete(sql = "UPDATE shop SET deleted = true WHERE id = ?")
@Where(clause = "deleted = false")
public class Shop {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String address;
private boolean deleted = Boolean.FALSE; // 삭제 여부 기본값 false
}
その後、クエリー(ex. shopRepository.findAll()
)を行うと、where条件が自動的に追加されます. select
shop0_.id as id1_11_,
shop0_.address as address2_11_,
shop0_.deleted as deleted3_11_,
shop0_.name as name4_11_
from
shop shop0_
where
(
shop0_.deleted = false
)
継承関係の場合
ソフトウェアdeleteを処理するエンティティは、継承関係である場合があります.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public abstract class Shop {
}
@Entity
@DiscriminatorValue("C")
public class Restaurant extends Shop {
}
@Entity
@DiscriminatorValue("R")
public class Cafe extends Shop {
}
親に対してのみ@SQLDelete(sql = "UPDATE shop SET deleted = true WHERE id = ?")
の処理を行うと、サブテーブルは実際に削除されます.下図に示すように、各サブクラスに対して
@OnDelete(action = OnDeleteAction.CASCADE)
の処理を行い、阻止することができる.@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
@SQLDelete(sql = "UPDATE shop SET deleted = true WHERE id = ?")
public abstract class Shop {
}
@Entity
@DiscriminatorValue("C")
@OnDelete(action = OnDeleteAction.CASCADE)
public class Restaurant extends Shop {
}
@Entity
@DiscriminatorValue("R")
@OnDelete(action = OnDeleteAction.CASCADE)
public class Cafe extends Shop {
}
reference
Reference
この問題について(自動処理[JPA]ソフトdelete), 我々は、より多くの情報をここで見つけました https://velog.io/@max9106/JPA-soft-deleteテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol