【问题标题】:Hibernate ObjectNotFoundException, but object existsHibernate ObjectNotFoundException,但对象存在
【发布时间】:2014-05-29 20:33:45
【问题描述】:

编辑:错误是对的,别介意。


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

所以,我的应用程序是一个Call 跟踪应用程序。它有Users,为了知道一个User是否可用,我们有一个名为ResourceAvailability的类:

class ResourceAvailability {

    def grailsApplication

    Call            callInstance
    User            resource
    ResourceStatus  resourceStatus
    Date            dateCreated

// ... constraints, etc ...

}

(没有从用户返回到 ResourceAvailability 的链接。)

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

没有一堆错误处理代码,下面是 Call 控制器的 accept 操作的核心:

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:

这似乎发生在我从 Grails 2.2.0 升级到 2.3.8 时。我仍然有 2.2.0 版本,并且相同的代码在那里工作。

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

我已经对代码进行了加工,并且 User 实例存在于服务内部,在 new ResourceAvailability 行之前和之后。

编辑 所以我在登录 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

为什么它在插入后做select,为什么它使用user.id of 0???

编辑将我的 Grails Hibernate 插件升级到 3.6.10.15。没有解决问题:/

【问题讨论】:

  • 你为什么要传入Userid,然后再传入read,你已经拥有来自springSecurityService.currentUser 的用户实例?
  • @dmahapatro 我想也许该实例在服务事务结束时已关闭或丢失,所以我尝试将其更改为这个,但还没有改回来。

标签: hibernate session grails transactions


【解决方案1】:

果然:我添加了一个callCompletedUser 字段但没有填充它,在 2.3.8 中它的默认值是 0 而不是 null。因此,Hibernate 抱怨找不到 id 为 0 的用户。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 2011-05-26
    • 2015-03-01
    • 2014-10-13
    • 2011-08-12
    • 1970-01-01
    相关资源
    最近更新 更多