3

ユーザーを DB から削除しないようにする方法を探していましたが、代わりに削除済みとしてマークし、クエリに戻さないようにしました。

このプラグインhttp://grails.org/plugin/hibernate-filterを見つけました。これは、タスクに最適なツールでした。

しかし、解決策を実装しようとしたとき、解決策がインターネット上にない (または見つけることができなかった) 同じ問題に合格しました。

そこで、次に、ソフト削除の問題を解決する方法について説明します。

4

2 に答える 2

5

この例では、User インスタンスで delete() が呼び出されたときに属性 lowDate を実際の日付に設定して、その delete() メソッドをソフト削除として処理するようにクラス User を作成します。lowDate != null を持つユーザーは GORM クエリによって無視されるという考え方です。

1) Hibernate Filter Plugin をインストールします。プラグインのページで依存関係を探します: http://grails.org/plugin/hibernate-filter。ドキュメントを見てください。

2) 以下をデータソースに追加します。

import org.grails.plugin.hibernate.filter.HibernateFilterDomainConfiguration

environments {
    development {
    dataSource {
        ...    
        configClass = HibernateFilterDomainConfiguration
    }
    }
    test {
    dataSource {
        ...
        configClass = HibernateFilterDomainConfiguration
    }
    }
    production {
    dataSource {
        ...
        configClass = HibernateFilterDomainConfiguration
    }
    }   
}

3) クラスでフィルターを定義します。

class User {
    ...
    String email
    Date lowDate
    static hibernateFilters = {
        deletedFilter(condition:'low_date is null', default:true)
    }
    static constraints = {
        ...
        lowDate nullable: true
    }
    ...
}

注: 条件の定義方法を見てください。受け取る値は sql であるため、クラスの名前ではなく、データベースにある属性の名前を慎重に付けてください。

これにより、GORM メソッドは、lowDate が null 以外のユーザーを持ち込まないようになります。

4) 物理的な削除を回避する方法で beforeDelele を定義します。

class User {
    ...
    def beforeDelete() {
        SecUser.executeUpdate("update SecUser su set lowDate = :lowDate where email = :email",
                                [lowDate: new Date(), email: email])
        return false
    }
}

注: beforeDelete() を実装する簡単な方法を試しました。

def beforeDelete() {
    this.lowDate = new Date()
    this.save()
    return false
}

しかし、save() が beforeDelete 内で呼び出されると、save メソッドが beforeDelete を呼び出すなどして、StackOverflow が生成されます。なぜこれが起こるのかわかりません。

5) BootStrap でフィルターを有効にします。

class BootStrap {
    ...
    def init = { servletContext ->
        User.enableHibernateFilter('deletedFilter')
        environments {
            ...
        }
    }
...
}

以上で、動作するようになりました。機能をテストするために、いくつかのサンプル スポック テストを次に示します。

注: 「build」メソッドは build-test-data プラグインからのものです。

class UserIntegrationSpec extends IntegrationSpec {

    def 'it should not find users marked as deleted'(){
        given: 'some users with lowDate and some withOut lowDate (=null)'
            User.build(firstName:'delUser1', lowDate: new Date())
            User.build(firstName:'user1')
            User.build(firstName:'delUser2', lowDate: new Date())
            User.build(firstName:'user2')
            def users = User.list()
        expect: 'it should only find the ones with lowDate == null'
            users.size() == 2
            users.every { it.firstName == 'user1' || it.firstName == 'user2' }      
    }

    def 'it should only delete users logically' (){
        given: 'a persisted user'
            def user = User.build(firstName: 'logiDelUser')
        when: 'user.delete() is called'
            user.delete(failOnError:true, flush:true)
            def deletedUser
            def users 
            User.withoutHibernateFilters(){
                users = User.list()
                deletedUser = User.find { firstName == 'logiDelUser' }
            }
        then: 'it should not delete the user from the DB, but set a low date instead'
            users.size() != 0
            deletedUser.lowDate != null
            deletedUser.firstName == 'logiDelUser' 
    }
}

それが役立つことを願っています!

于 2012-09-17T21:31:30.213 に答える
1

GORM でエンティティのソフト削除を行う別の方法は、次のプラグインを使用することです。

http://grails.org/plugin/logical-delete

「削除済み」フラグを使用してエンティティを削除済みとしてマークし、クエリには表示されません。このプラグインはHibernate フィルター プラグインを使用します

于 2014-02-02T03:53:32.730 に答える