【问题标题】:Grails, custom validator, Hibernate assertion errorGrails,自定义验证器,Hibernate 断言错误
【发布时间】:2015-05-27 13:11:38
【问题描述】:

我正在尝试在我的域类中使用服务进行自定义验证。在其他领域类中,这工作得很好,但在这里我收到一个 Hibernate 断言错误。

域类自定义验证:

end validator: { val, obj ->

    if (obj.userWorkingTimeRegulationService.validateit() == false){
        return ["error.workingregulation"]
    }

我使用以下方法注入服务:

def userWorkingTimeRegulationService

该服务仅返回 true 用于测试目的:

package usermanagement

import grails.transaction.Transactional

@Transactional
class UserWorkingTimeRegulationService {

    def serviceMethod() {

    }

    def validateit(){
        return true
    }
}

堆栈跟踪:

| Error 2015-05-27 15:07:54,909 [localhost-startStop-1] ERROR hibernate.AssertionFailure  - HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: null id in usermanagement.UserWorkingTimeRegulation entry (don't flush the Session after an exception occurs)
| Error 2015-05-27 15:07:54,927 [localhost-startStop-1] ERROR context.GrailsContextLoaderListener  - Error initializing the application: null id in usermanagement.UserWorkingTimeRegulation entry (don't flush the Session after an exception occurs)
Message: null id in usermanagement.UserWorkingTimeRegulation entry (don't flush the Session after an exception occurs)
    Line | Method
->>   24 | doCall                           in usermanagement.UserWorkingTimeRegulation$__clinit__closure4$_closure8
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     47 | onApplicationEvent               in org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
|     52 | create . . . . . . . . . . . . . in usermanagement.UserWorkingTimeRegulation
|     47 | doCall                           in BootStrap$_closure1
|    327 | evaluateEnvironmentSpecificBlock in grails.util.Environment
|    320 | executeForEnvironment            in     ''
|    296 | executeForCurrentEnvironment . . in     ''
|    266 | run                              in java.util.concurrent.FutureTask
|   1142 | runWorker . . . . . . . . . . .  in java.util.concurrent.ThreadPoolExecutor
|    617 | run                              in java.util.concurrent.ThreadPoolExecutor$Worker
^    745 | run . . . . . . . . . . . . . .  in java.lang.Thread
Error |
Forked Grails VM exited with error

如果我使用在域类中声明的方法都可以,那肯定是服务有问题。在另一个域类中,我在自定义验证中使用服务没有问题,我不知道这个有什么特别之处。

编辑:

我在我的Bootstrap.groovy 中创建了一个 UserWorkingTimeRegulation,如果我在我的域类中注释自定义验证,它不应该做任何事情,因为服务返回 true 并且验证以false 启动,它会被正确保存。

引导程序:

UserWorkingTimeRegulation.create adminUser, workingTimeRegulation, new LocalDate(), new LocalDate().plusMonths(1)

【问题讨论】:

    标签: grails grails-orm


    【解决方案1】:

    服务默认是事务性的 - 使服务非事务性的唯一方法是添加 static transactional = false 并删除所有 @Transactional 注释。 Spring/Hibernate 事务管理器总是在成功的事务结束时刷新 Hibernate 会话,所以你看到的是在调用服务方法之后(即使是像你这样没有持久性的方法),所有修改过的持久性对象都会从Hibernate 缓存到数据库,但其中一个有问题。

    错误消息相当神秘,但它表示usermanagement.UserWorkingTimeRegulation 没有ID。这意味着您调用了save(),但它没有验证,因此您需要通过调用hasErrors 和/或getErrors 检查哪些值丢失或无效。没有 id 是个问题的原因是这个实例是另一个域对象的属性,而 id 被用作将它们链接在一起的外键。

    附言随意删除未使用的自动生成的serviceMethod 方法。

    【讨论】:

    • 谢谢! static transactional = false 一切正常。但我真的不明白为什么。该服务返回true,而我的自定义验证中的if 语句只为false 启动。 UserWorkingTimeRegulation 是在我的bootstrap.groovy 中创建的,我在最初的帖子中对其进行了编辑。如果没有自定义验证,所有内容都会正确保存。此实例不是另一个域类的属性,因为它用作用户和工作时间规则的多对多映射。我真的很想了解这个事务服务如何影响实例而不接触它
    • 我应该将这样的逻辑(验证)放在服务中还是将其直接保存在域类中更好?这里的最佳做法是什么?
    • 没有什么会自动改变你的持久化实例——你的代码中的某些东西正在这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多