I ran into this issue today when trying to persist one of my
objects. The cause of the problem was interesting. I was trying to
save an object when a property/columns in the table had a unique
constraint. As a result, the object that I was trying to persist would
not persist simply because the object's property it failed to meet the
unique constraint.
As a result, a call to Save() on the object
failed and the ID on the object I was trying to save was not set, but Grails Hibernate still processed the object and associated it with its
persistence mechanism leaving it in a "semi-persistent" state with the Grails Hibernate persistence manager (ie: Grails Hibernate now knows about the
object you tried to save and it SHOULD have fully evicted the object
from its persistence manager because the save failed, but it didn't).
So, the solution that I
implemented was to wrap the Save() in a try{} catch{} statement and handling exception.
Basically you need to do something like this:
Create a Filters in conf directory under grails project suppose named 'BaseFilters.groovy' with the following content:
import org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext
import org.codehaus.groovy.grails.web.context.ServletContextHolder
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes
import org.hibernate.FlushMode
import org.hibernate.Session
import org.hibernate.SessionFactory
class BaseFilters {
private static GrailsWebApplicationContext ctx;
def filters = {
all(controller:'*', action:'*') {
before = {
Session session = getRequestSession();
session.setFlushMode(FlushMode.MANUAL)
request.requestSession = session;
}
after = { Map model ->
try {
Session session = request.requestSession;
session.flush();
} catch (Exception ex) {
ex.printStackTrace()
}
}
afterView = { Exception e ->
}
}
}
private Session getRequestSession() {
createCtx();
SessionFactory sessionFactory = ctx.sessionFactory
Session session = sessionFactory.currentSession
return session;
}
private def createCtx() {
if(!ctx) {
ctx = ServletContextHolder.servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
}
}
}
Originally session flush mode initially set to 'FlushMode.AUTO' which cause the error.
So I change the session flush mode to 'FlushMode' to 'MANUAL'.
And also make your service transaction false such: static transactional = false, add this line just below the class definition.
And in the after section, I just manually try to flush, which is not much needed, you can ignore it.
I just add this section to do some logic manually if need.