27. 論理削除とは何か?どのような解法があるのか? w/ twada | Fukabori.fm論理削除の会の話が非常に勉強になりました。
個人的に、使うことが多いEclipseLink と、Django の論理削除の実現方法に興味を持ったので、どんな方法があるのか調べてみました。
結果を記載します。


State Machineのプラグイン

fukabori.fm会話の中で、論理削除を示すフラグではなく、データの状態をステータスで管理するパターンが話されています。
ORM では、State Machine探すと、ORMでの該当する実現方法が出てくるそうです。


EclipseLink だとEclipseLink State Machine見つけられず、EclipseLink Soft Deleteついて調べてみました。
以下の記事が見つかります。

読んだ限り、以下のような流れで論理削除は実現できそうに思いました。

@AdditionalCriteria を使用して、表示対象のデータを制限する

@AdditionalCriteria を Entity クラスに付与すると、デフォルトでWHERE句を付与できます。

@Entity
@AdditionalCriteria("this.status <> 'deleted'")
public class Employee {
  @Id
  @Column(name="EMP_ID")
  private long id;
  @Basic
  private String status; // This is optional, as a query-key could also be used.
}

@Customizer を使って、削除時の動作を変更する

Entity クラスに、@Customizer付与し、DescriptorCustomizer実装クラスを指定します。

@Entity
@Table(name="ITEM")
@Customizer(SoftDeleteCustomizer.class)
public class Item {
    ////

}

DescriptorCustomizer customize メソッドを実装します。

public class SoftDeleteCustomizer implements DescriptorCustomizer {
  public void customize(ClassDescriptor descriptor) {
    descriptor.getQueryManager()
    .setDeleteSQLString("Update ITEM set ITEM_STATUS = 2 where ITEM_ID = #ITEM_ID"); 
} 

DescriptorQueryManager#setDeleteSQLString Entity の DELETE操作時に発行するSQLを変更できます。

DescriptorQueryManager の 実装は以下になります。
eclipselink/DescriptorQueryManager.java at master · eclipse-ee4j/eclipselink

DBへのステータス登録はこれらの機能を使って実現できそうです。

Java でのステートマシン

EclipseLink では、ステートマシン実装はなかったので、以下のような、ステートマシンライブラリを使うのが良いかなと思いました。

Entity クラスの ステータスフィールド の setter でステートマシンを呼び出すような実装になるかなと思いました。


Django の論理削除の実現方法

Django には、State Machine も、Soft Delete双方ありましたのでそれぞれ記載します。

State Machine

Django State Machine検索すると以下が見つかります。有限 State Machineプラグインです。

上記の中では、django-fsm使いやすいかなと思いました。
* viewflow/django-fsm: Django friendly finite state machine support

django の admin で使うための拡張も存在します。

Soft Delete

Django Soft Delete検索すると以下が見つかります。

deleted_atいう日付フィールドを使って、論理削除を実現しています。
ChangeSetいう履歴管理のためのModel と admin が用意されていて、手が込んでいます。

個人的に Django で 論理削除を行うとしたら、django-fsm使おうかなと思います。


参考

ステートマシンって何だっけ? になり、以下の記事を見ました。

以上です。

コメント