Permalink
Browse files

Fix for GRAILS-9055 - A SELECT query is always performed before INSER…

…T even when insert: true and generator: 'assigned'
  • Loading branch information...
1 parent 26e6b95 commit d1635f6256a52b1d9fd4386392f311f1460b9051 @lhotari lhotari committed Apr 25, 2012
View
14 .../main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/SavePersistentMethod.java
@@ -21,6 +21,7 @@
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.commons.GrailsDomainClass;
import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore;
+import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
@@ -67,11 +68,16 @@ public Object doInHibernate(Session session) throws HibernateException, SQLExcep
protected Object performInsert(final Object target, final boolean shouldFlush) {
return getHibernateTemplate().execute(new HibernateCallback<Object>() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
- session.save(target);
- if (shouldFlush) {
- flushSession(session);
+ try {
+ ClosureEventTriggeringInterceptor.markInsertActive();
+ session.save(target);
+ if (shouldFlush) {
+ flushSession(session);
+ }
+ return target;
+ } finally {
+ ClosureEventTriggeringInterceptor.resetInsertActive();
}
- return target;
}
});
}
View
28 ...y/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java
@@ -85,6 +85,8 @@
private Method markInterceptorDirtyMethod;
private ApplicationContext ctx;
private Map<SessionFactory, HibernateDatastore> datastores;
+
+ private static final ThreadLocal<Boolean> insertActiveThreadLocal = new ThreadLocal<Boolean>();
public ClosureEventTriggeringInterceptor() {
try {
@@ -310,4 +312,30 @@ public boolean onPreInsert(PreInsertEvent event) {
return false;
}
}
+
+ /**
+ * Prevents hitting the database for an extra check if the row exists in the database
+ *
+ * ThreadLocal is used to pass the "insert:true" information to Hibernate
+ *
+ * @see org.hibernate.event.def.AbstractSaveEventListener#getAssumedUnsaved()
+ */
+ protected Boolean getAssumedUnsaved() {
+ return insertActiveThreadLocal.get();
+ }
+
+ /**
+ * Called by org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod's performInsert
+ * to set a ThreadLocal variable that determines the value for getAssumedUnsaved()
+ */
+ public static void markInsertActive() {
+ insertActiveThreadLocal.set(Boolean.TRUE);
+ }
+
+ /**
+ * Clears the ThreadLocal variable set by markInsertActive()
+ */
+ public static void resetInsertActive() {
+ insertActiveThreadLocal.remove();
+ }
}

0 comments on commit d1635f6

Please sign in to comment.