使用Hibernate Filters Plugin软删除Grails中的实体 [英] Soft delete an entity in Grails with Hibernate Filters Plugin

查看:144
本文介绍了使用Hibernate Filters Plugin软删除Grails中的实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种避免将我的用户从数据库中删除的方法,而是将它们标记为已删除,并且不要将它们带回查询中。

我发现这个插件 http://grails.org/plugin/hibernate-filter ,这是一个伟大的工具的任务。



但是当我试图实施我的解决方案时,我通过了在互联网上解决了哪些问题(或者我无法找到)的相同问题。

因此,接下来,我将描述我解决软删除问题的方法。 解决方案方案

在这个例子中,我将使我的类User将它的delete()方法作为软删除来处理,在用户实例上调用delete()时将属性lowDate设置为实际日期。这个想法是,具有lowDate!= null的用户将被GORM查询忽略。


$ b

1)Intall 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
}
}
生产{
dataSource {
...
configClass = HibernateFilterDomainConfiguration
}
}
}

3)在类中定义过滤器:

  class User {
...
字符串电子邮件
日期lowDate
static hibernateFilters = {
deletedFilter(condition:'low_date is null',default:true)
}
静态约束= {
...
lowDate可空:t rue
}
...
}

注意:外观在我定义条件的方式。它收到的值是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 ,保存方法叫做beforeDelete,等等,生成一个StackOverflow。我不知道为什么会发生这种情况。


$ b $ 5在BootStrap上启用过滤器:

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

就是这样,它现在显示工作。为了测试函数的完整性,下面是一些spock示例测试:注意:'build'方法来自build-test-data插件。

  class UserIntegrationSpec extends IntegrationSpec {
$ b $ def'它不应该找到标记为已删除的用户'(){
given:'some用户使用lowDate和一些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: '它应该只能找到lowDate == null'
users.size()== 2
users.every {it.firstName =='user1'|| it.firstName =='user2'}
}

def'它应该只能从逻辑上删除用户'(){
给定:'持久用户'
def user = User.build(firstName:'logiDelUser')
当:'user.delete()被称为'
user.delete(failOnError:true,flush:true)
def deletedUser
def users
User.withoutHibernateFilters(){
users = User.list()
deletedUser = User.find {firstName =='logiDelUser'}
}
then:'它不应该从数据库中删除用户,而是设置一个低日期'
users.size()!= 0
deletedUser.lowDate!= null
deletedUser。 firstName =='logiDelUser'
}
}

希望有帮助!

I was looking for a way to avoid deleting my users from DB, but instead to mark them as deleted and don't bring them back in queries.

I found this plugin http://grails.org/plugin/hibernate-filter, which was a great tool for the task.

But when I tried to implement my solution, I passed trought same problems whose solutions wheren't (or I was not able to find) on internet.

So, next, I describe the way that I solve the problem of soft delete.

解决方案

In this example I will make my class User to handle it's delete() method as a soft delete, setting the attribute lowDate with the actual date when delete() is called on an User instance. The idea is that users with lowDate != null will be ignored by GORM queries.

1) Intall Hibernate Filter Plugin. Look for the dependency at the plugin's page: http://grails.org/plugin/hibernate-filter. Take a look at the documentation.

2) Add to Datasource the following:

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

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

3) Define your filter at the class:

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

Note: look at the way I defined the condition. The value it receives is sql, so be careful to name the attribute as it is on the database instead of the name on the class.

This will make GORM methods to avoid bringing users that have lowDate different than null.

4) Define beforeDelele in a way to avoid phisical deletion:

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

Note: I tried a simpler way to implement beforeDelete() that was

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

But when save() was called inside beforeDelete, the save method called beforeDelete, and so on, generating an StackOverflow. I don't know why this happens.

5) Enable the filter on BootStrap:

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

That's all, it show now work. To test the functionallity, here's some sample spock tests:

Note: 'build' method is from build-test-data plugin.

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' 
    }
}

Hope that that helps!

这篇关于使用Hibernate Filters Plugin软删除Grails中的实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆