Permalink
Browse files

fix for GRAILS-4453

  • Loading branch information...
graemerocher committed Jul 22, 2009
1 parent 141995c commit 81f3dc3cf619cede2638331e938f9c5f9103d612
@@ -0,0 +1,55 @@
+/* Copyright 2004-2005 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.groovy.grails.orm.hibernate.events;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
+import org.hibernate.event.EventSource;
+import org.hibernate.event.def.DefaultFlushEventListener;
+
+/**
+ * Patches Hibernate to prevent this issue
+ * http://opensource.atlassian.com/projects/hibernate/browse/HHH-2763
+ *
+ * TODO: Remove this patch when HHH-2763 is resolved
+ *
+ * @author Graeme Rocher
+ * @since 1.2
+ */
+public class PatchedDefaultFlushEventListener extends DefaultFlushEventListener{
+
+ private static final Log LOG = LogFactory.getLog(PatchedDefaultFlushEventListener.class);
+ @Override
+ protected void performExecutions(EventSource session) throws HibernateException {
+ session.getPersistenceContext().setFlushing(true);
+ try {
+ session.getJDBCContext().getConnectionManager().flushBeginning();
+ // we need to lock the collection caches before
+ // executing entity inserts/updates in order to
+ // account for bidi associations
+ session.getActionQueue().prepareActions();
+ session.getActionQueue().executeActions();
+ }
+ catch (HibernateException he) {
+ LOG.error("Could not synchronize database state with session", he);
+ throw he;
+ }
+ finally {
+ session.getPersistenceContext().setFlushing(false);
+ session.getJDBCContext().getConnectionManager().flushEnding();
+ }
+ }
+}
@@ -56,6 +56,7 @@ import org.apache.commons.beanutils.PropertyUtils
import org.hibernate.Hibernate
import org.springframework.validation.Validator
import org.hibernate.EmptyInterceptor
+import org.codehaus.groovy.grails.orm.hibernate.events.PatchedDefaultFlushEventListener
/**
@@ -168,7 +169,8 @@ Try using Grails' default cache provider: 'org.hibernate.cache.OSCacheProvider'"
grailsApplication = ref("grailsApplication", true)
lobHandler = lobHandlerDetector
entityInterceptor = entityInterceptor
- eventListeners = ['pre-load':eventTriggeringInterceptor,
+ eventListeners = ['flush': new PatchedDefaultFlushEventListener(),
+ 'pre-load':eventTriggeringInterceptor,
'post-load':eventTriggeringInterceptor,
'save':eventTriggeringInterceptor,
'save-update':eventTriggeringInterceptor,
@@ -0,0 +1,71 @@
+package org.codehaus.groovy.grails.orm.hibernate
+
+
+/**
+ * @author Graeme Rocher
+ * @since 1.1
+ */
+
+public class AssertionFailureInEventTests extends AbstractGrailsHibernateTests{
+
+ protected void onSetUp() {
+ gcl.parseClass('''
+import grails.persistence.*
+
+@Entity
+class AssertionParent {
+ static hasMany = [ childs : AssertionChild ]
+
+ def beforeUpdate =
+ {
+ calc()
+ }
+
+ def calc =
+ {
+ this.childs.each {
+ it.s = "change"
+ }
+
+ }
+}
+
+@Entity
+class AssertionChild {
+ static belongsTo = [AssertionParent];
+ static hasMany = [ subChilds : AssertionSubChild ]
+ String s
+}
+
+@Entity
+class AssertionSubChild {
+ static belongsTo = [AssertionChild];
+ String s
+}
+''')
+ }
+
+
+ // test for HHH-2763 and GRAILS-4453
+ void testNoAssertionErrorInEvent() {
+ def Parent = ga.getDomainClass("AssertionParent").clazz
+ def Child = ga.getDomainClass("AssertionChild").clazz
+ def p = Parent.newInstance().save()
+ p.addToChilds(Child.newInstance(s:"one"))
+ p.save(flush:true)
+
+ session.clear()
+
+ p = Parent.findById(1, [fetch:[childs:'join']])
+
+ p.addToChilds(Child.newInstance(s:"two"))
+ p.save(flush:true)
+
+ session.clear()
+
+ p = Parent.get(1)
+ p.childs.each { println it.s }
+ }
+
+
+}

0 comments on commit 81f3dc3

Please sign in to comment.