使用Hibernate Filters Plugin软删除Grails中的实体 [英] Soft delete an entity in Grails with Hibernate Filters Plugin
问题描述
我正在寻找一种避免将我的用户从数据库中删除的方法,而是将它们标记为已删除,并且不要将它们带回查询中。
我发现这个插件 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屋!