【问题标题】:Grails - DuplicateKeyExceptionGrails - DuplicateKeyException
【发布时间】:2013-07-31 22:39:22
【问题描述】:

我有以下将新对象添加到数据库的代码。首先,它从数据库中获取另一个对象并添加到最终对象中。

我的几行代码

            ClassC c = ClassC.findByName(cName)

            ClassD d = new ClassD(
                    name: "WHATEVER",
                    classC: c
            )

            print "AAA\n"

            ClassC.withTransaction {
                c = c.merge()
                // c.save(failOnError: true, flush: true)
            }

            print "BBB\n"

            // ClassD.withTransaction {
            //     d = d.merge()
            // }
            // print "CCC\n"

            ClassD.withTransaction {
                d.save(failOnError: true, flush: true)
            }

            print "DDD\n"

我收到以下错误:

AAA
BBB

2013-07-31 13:57:14,279 ERROR JobRunShell - Job DEFAULT.1 threw an unhandled Exception: 
 org.springframework.dao.DuplicateKeyException: a different object with the same identifier value was already associated with the session: [xxx.ClassD#15]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [xxx.ClassD#15]

你能帮帮我吗?

谢谢


ClassC.withTransaction {
    ClassC c = ClassC.findByName(cName)

    // find the record with name: "WHATEVER" or create a new one if there is none
    ClassD d = ClassD.findOrCreateWhere(name: "WHATEVER")

    c = c.merge()
    c.addToClassesD(d) // static hasMany = [classesD: ClassD] <-- in ClassC domain
    c.save(failOnError: true, flush: true)
}

错误来自行

c.addToClassesD(d)

:

java.lang.IllegalStateException:未找到线程绑定请求:是 您指的是实际 Web 请求之外的请求属性, 或在原始接收线程之外处理请求?如果 你实际上是在一个网络请求中操作并且仍然收到这个 消息,您的代码可能在 DispatcherServlet/DispatcherPortlet:在这种情况下,使用 RequestContextListener 或 RequestContextFilter 暴露当前 要求。在 org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) 在 org.springframework.web.context.request.RequestContextHolder$currentRequestAttributes.call(未知 来源)在 xxx.AuditLogService.getCurrentUser(AuditLogService.groovy:127) 在 xxx.AuditLogService$getCurrentUser.callStatic(Unknown Source) at xxx.AuditLogService$_closure2.doCall(AuditLogService.groovy:58) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:597) 在 org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1243) 在 org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) 2013-08-02 09:39:11,110 错误 ErrorLogger - 作业(DEFAULT.1 抛出 例外。 org.quartz.SchedulerException:作业抛出了一个未处理的 例外。在 org.quartz.core.JobRunShell.run(JobRunShell.java:224) 在 org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557) 引起:java.lang.IllegalStateException:没有线程绑定请求 发现:您指的是实际之外的请求属性吗? Web 请求,或处理原始请求之外的请求 接收线程?如果您实际上是在 Web 请求中操作 仍然收到此消息,您的代码可能在外面运行 DispatcherServlet/DispatcherPortlet:在这种情况下,使用 RequestContextListener 或 RequestContextFilter 暴露当前 要求。在 org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) 在 org.springframework.web.context.request.RequestContextHolder$currentRequestAttributes.call(未知 来源)在 xxx.AuditLogService.getCurrentUser(AuditLogService.groovy:127) 在 xxx.AuditLogService$getCurrentUser.callStatic(Unknown Source) at xxx.AuditLogService$_closure2.doCall(AuditLogService.groovy:58) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:597) 在 org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1243) 在 org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)

【问题讨论】:

  • 嘿,伙计!您可以尝试我的答案中的解决方案吗?

标签: hibernate grails transactions


【解决方案1】:

您可能应该只在一个事务中完成所有操作。

至于您遇到的错误,我假设您为 name 设置了 unique -- 如果已经有一条名为“WHATEVER”的记录,您将收到该错误。

您可能想要这样做:

ClassC.withTransaction {
    ClassC c = ClassC.findByName(cName)

    // find the record with name: "WHATEVER" or create a new one if there is none
    ClassD d = ClassD.findOrCreateWhere(name: "WHATEVER")

    c = c.merge()
    d.classC = c
    d.save(failOnError: true, flush: true)
}

【讨论】:

  • 嗨!我只是复制了一段代码。在实际代码中没有“WHATEVER”而是更复杂的数据,所以不用担心——它总是唯一的。错误来自 org.hibernate.NonUniqueObjectException
  • 好吧,当您手动初始化具有 id 或唯一属性的类 new ClassD 时,当会话中已经有另一个类时,就会出现这个问题。因此,您应该首先尝试获取该实体(这就是 findOrCreateWhere 所做的,但如果您使用 id,则需要使用 get),然后使用找到的实例或创建一个新的实例进行更新。
  • 嗨,我阅读了您的提示并更新了我的帖子。现在,我遇到了另一个错误。你能看一下吗?
【解决方案2】:

看看 AuditLogService。您似乎正在对域类(或 Hibernate)实施某种审计或安全,这需要一个安全上下文,而您在外部调用此代码。

另外,只是出于好奇,你为什么要在 c 上调用 .merge()?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-30
    • 2013-05-04
    • 1970-01-01
    • 2017-02-05
    • 1970-01-01
    • 2018-02-22
    • 2012-02-13
    相关资源
    最近更新 更多