Hibernate ObjectNotFoundException,但对象存在

Hibernate ObjectNotFoundException,但对象存在,hibernate,session,grails,transactions,Hibernate,Session,Grails,Transactions,编辑:错误是正确的,请不要介意 TL;DR:当我试图在一个服务中的两个实例之间创建链接时,Hibernate会抱怨其中一个实例没有找到,即使它确实存在。这似乎是在升级到Grails 2.3.8之后开始出现的。 因此,我的应用程序是一个调用跟踪应用程序。它有用户,为了知道用户是否可用,我们有一个名为ResourceAvailability的类: class ResourceAvailability { def grailsApplication Call

编辑:错误是正确的,请不要介意


TL;DR:当我试图在一个服务中的两个实例之间创建链接时,Hibernate会抱怨其中一个实例没有找到,即使它确实存在。这似乎是在升级到Grails 2.3.8之后开始出现的。

因此,我的应用程序是一个
调用
跟踪应用程序。它有
用户
,为了知道用户是否可用,我们有一个名为
ResourceAvailability
的类:

class ResourceAvailability {

    def grailsApplication

    Call            callInstance
    User            resource
    ResourceStatus  resourceStatus
    Date            dateCreated

// ... constraints, etc ...

}
(用户与ResourceAvailability之间没有链接。)

当用户登录、接受呼叫或以其他方式更改状态时,其以前的可用性状态将从表中删除,并创建一个新状态。这样,我们就可以跟踪某人已经准备好了多长时间,例如,在电话等待时,或者他们已经接受电话多长时间了

在没有大量错误处理代码的情况下,以下是
调用
控制器的
接受
操作的要点:

def accept(Long id, Long version) {

    // All the Call stuff works fine...
    def callInstance = Call.get(id)
    callInstance.accept()
    callInstance.save()
    def user = springSecurityService.currentUser

    // Clear out the user's existing Ready or Busy status
    // TODO: Factor out into a service method
    ResourceAvailability.where {
        resource == user && (resourceStatus.statusDescription == "Ready" || resourceStatus.statusDescription == "Busy")
    }?.each { it.delete() }


    // Set new status. The error occurs in this method.
    resourceAvailabilityService.setResourceStatus(user.id, 'Accepted', callInstance)

    // redirect to view

}
以及
setResourceStatus
方法:

void setResourceStatus(Long userId, String resourceStatusDescription, Call callInstance = null) {
    def resource = User.read(userId)

    ResourceStatus resourceStatus = ResourceStatus.findByStatusDescription(resourceStatusDescription)

    /** HERE'S THE PROBLEM LINE **/
    ResourceAvailability resourceAvailabilityInstance = new ResourceAvailability (
        callInstance: callInstance,
        resource: resource,
        resourceStatus: resourceStatus
    ).save(flush: true, failOnError: true)

    new ResourceHistory(resourceAvailabilityInstance).save(flush: true, failOnError: true)

}
尝试保存新的
ResourceAvailability
时发生异常。(如果我删除
flush:true
,它将在事务提交时发生在方法末尾。)

以下是例外情况供参考:

ERROR errors.GrailsExceptionResolver  - ObjectNotFoundException occurred when processing request: [GET] /CallLog/call/accept/17779
No row with the given identifier exists: [com.foobar.calls.User#0]. Stacktrace follows:
这似乎是在我从Grails2.2.0升级到2.3.8时发生的。我仍然有2.2.0版本,同样的代码在那里工作

我引用的
用户(也称资源)肯定存在。这在单元测试期间不会发生;我正在运行应用程序并登录。就在调用此方法时,Hibernate似乎失去了对用户的跟踪

我已经对代码进行了加工,并且用户实例存在于服务内部,
newresourceavability
行之前和之后

编辑 因此,我在SQL登录时再次运行了该方法,并注意到:

2014-05-29 16:10:23,806 [http-bio-8080-exec-7] DEBUG hibernate.SQL  - insert into resource_availability (version, call_instance_id, date_created, resource_id, resource_status_id) values (?, ?, ?, ?, ?)
2014-05-29 16:10:23,807 [http-bio-8080-exec-7] TRACE sql.BasicBinder  - binding parameter [1] as [BIGINT] - 0
2014-05-29 16:10:23,807 [http-bio-8080-exec-7] TRACE sql.BasicBinder  - binding parameter [2] as [BIGINT] - 17779
2014-05-29 16:10:23,808 [http-bio-8080-exec-7] TRACE sql.BasicBinder  - binding parameter [3] as [TIMESTAMP] - Thu May 29 16:10:23 CDT 2014
2014-05-29 16:10:23,808 [http-bio-8080-exec-7] TRACE sql.BasicBinder  - binding parameter [4] as [BIGINT] - 30
2014-05-29 16:10:23,808 [http-bio-8080-exec-7] TRACE sql.BasicBinder  - binding parameter [5] as [BIGINT] - 1
2014-05-29 16:10:23,826 [http-bio-8080-exec-7] DEBUG hibernate.SQL  - select user0_.id as id24_0_, user0_.version as version24_0_, user0_.account_expired as account3_24_0_, user0_.account_locked as account4_24_0_, user0_.enabled as enabled24_0_, user0_.first_name as first6_24_0_, user0_.last_name as last7_24_0_, user0_.`password` as password8_24_0_, user0_.password_expired as password9_24_0_, user0_.resource_level_id as resource10_24_0_, user0_.username as username24_0_ from user user0_ where user0_.id=?
2014-05-29 16:10:23,826 [http-bio-8080-exec-7] TRACE sql.BasicBinder  - binding parameter [1] as [BIGINT] - 0
为什么它在插入后执行
选择
,为什么使用0的
user.id


编辑将我的Grails Hibernate插件升级到3.6.10.15。没有解决问题:///p>果然:我添加了一个
callCompletedUser
字段,但没有填充它,在2.3.8中,它的默认值是0而不是null。所以Hibernate抱怨找不到id为0的用户。

为什么要传入
User
id
,然后再次
springSecurityService.currentUser
?@dmahapatro那里读取
,因为你已经有了
springSecurityService.currentUser
?@dmahapatro,我想可能是该实例正在关闭或丢失服务事务的结束,所以我尝试将其更改为此,但尚未将其更改回。