Tom*_*ero 3 grails grails-orm soft-delete hibernate-filters
我一直在寻找一种方法来避免从数据库中删除我的用户,而是将它们标记为已删除,并且不会将它们带回查询中.
我找到了这个插件http://grails.org/plugin/hibernate-filter,这是一个很棒的工具.
但是当我试图实施我的解决方案时,我通过了相同的问题,其解决方案在互联网上没有(或者我无法找到).
接下来,我描述了解决软删除问题的方法.
在这个例子中,我将使我的类User将delete()方法作为软删除处理,将属性lowDate设置为在User实例上调用delete()时的实际日期.这个想法是GORM查询将忽略具有lowDate!= null的用户.
1)Intall Hibernate Filter插件.在插件页面上查找依赖项: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
}
}
}
Run Code Online (Sandbox Code Playgroud)
3)在课堂上定义你的过滤器:
class User {
...
String email
Date lowDate
static hibernateFilters = {
deletedFilter(condition:'low_date is null', default:true)
}
static constraints = {
...
lowDate nullable: true
}
...
}
Run Code Online (Sandbox Code Playgroud)
注意:看看我定义条件的方式.它接收的值是sql,因此要小心将属性命名为数据库而不是类上的名称.
这将使GORM方法避免使具有低于null的lowDate的用户.
4)以避免物理删除的方式定义beforeDelele:
class User {
...
def beforeDelete() {
SecUser.executeUpdate("update SecUser su set lowDate = :lowDate where email = :email",
[lowDate: new Date(), email: email])
return false
}
}
Run Code Online (Sandbox Code Playgroud)
注意:我尝试了一种更简单的方法来实现beforeDelete()
def beforeDelete() {
this.lowDate = new Date()
this.save()
return false
}
Run Code Online (Sandbox Code Playgroud)
但是当在beforeDelete中调用save()时,save方法调用beforeDelete,依此类推,生成StackOverflow.我不知道为什么会这样.
5)在BootStrap上启用过滤器:
class BootStrap {
...
def init = { servletContext ->
User.enableHibernateFilter('deletedFilter')
environments {
...
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
就是这样,它现在显示出来了.为了测试功能性,这里有一些spock测试示例:
注意:'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'
}
}
Run Code Online (Sandbox Code Playgroud)
希望这有帮助!