1
votes

I have got the following piece of code which adds new object to database. Firstly it takes another object from DB and add to the final object.

Few lines of my code

            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"

I have got the following error:

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]

Could you help me?

Thanks


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)
}

error goes from line

c.addToClassesD(d)

:

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) at org.springframework.web.context.request.RequestContextHolder$currentRequestAttributes.call(Unknown Source) at xxx.AuditLogService.getCurrentUser(AuditLogService.groovy:127) at xxx.AuditLogService$getCurrentUser.callStatic(Unknown Source) at xxx.AuditLogService$_closure2.doCall(AuditLogService.groovy:58) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1243) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) 2013-08-02 09:39:11,110 ERROR ErrorLogger - Job (DEFAULT.1 threw an exception. org.quartz.SchedulerException: Job threw an unhandled exception. at org.quartz.core.JobRunShell.run(JobRunShell.java:224) at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557) Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) at org.springframework.web.context.request.RequestContextHolder$currentRequestAttributes.call(Unknown Source) at xxx.AuditLogService.getCurrentUser(AuditLogService.groovy:127) at xxx.AuditLogService$getCurrentUser.callStatic(Unknown Source) at xxx.AuditLogService$_closure2.doCall(AuditLogService.groovy:58) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1243) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)

2
hey, man! can you try the solution in my answer?Elias Dorneles

2 Answers

2
votes

You probably should do it all inside one transaction only.

As for the error you are getting, I assume you have an unique set up for name -- you'll get that error when there is already a record with the name "WHATEVER" already.

You probably want to do something like this instead:

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)
}
0
votes

Take a look at AuditLogService. It seems you are implementing some sort of auditing or security on domain classes (or Hibernate) and this requires a security context, while you are calling this code outside one.

Also, just out of curiosity, why are you calling .merge() on c?