From c2dc1efabe932f1c2f165daa515b697e574f6a19 Mon Sep 17 00:00:00 2001 From: Puneet Behl Date: Wed, 29 Jan 2020 13:13:30 +0530 Subject: [PATCH 1/2] grails/grails-data-mapping#1272 Embedded object shouldn't be dirty after flush --- .../tests/dirtychecking/HibernateDirtyCheckingSpec.groovy | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/grails-datastore-gorm-hibernate5/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateDirtyCheckingSpec.groovy b/grails-datastore-gorm-hibernate5/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateDirtyCheckingSpec.groovy index f9075d521..cb6086afe 100644 --- a/grails-datastore-gorm-hibernate5/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateDirtyCheckingSpec.groovy +++ b/grails-datastore-gorm-hibernate5/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateDirtyCheckingSpec.groovy @@ -4,7 +4,6 @@ import grails.gorm.annotation.Entity import grails.gorm.dirty.checking.DirtyCheck import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore -import org.springframework.transaction.PlatformTransactionManager import spock.lang.AutoCleanup import spock.lang.Issue import spock.lang.Shared @@ -67,6 +66,12 @@ class HibernateDirtyCheckingSpec extends Specification { when: person.save(flush:true) + + then: + !person.address.hasChanged() + person.address.listDirtyPropertyNames().isEmpty() + + when: hibernateDatastore.sessionFactory.currentSession.clear() person = Person.first() From 94d67a9bef7b4e0580102435388f1c36c3a547a5 Mon Sep 17 00:00:00 2001 From: Puneet Behl Date: Wed, 29 Jan 2020 13:15:33 +0530 Subject: [PATCH 2/2] grails/grails-data-mapping#1272 Reset dirty in embedded objects Updated GrailsEntityDirtinessStrategy.groovy to also reset dirty embedded objects. --- .../GrailsEntityDirtinessStrategy.groovy | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/grails-datastore-gorm-hibernate5/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy b/grails-datastore-gorm-hibernate5/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy index afcbc48c5..e9c442c61 100644 --- a/grails-datastore-gorm-hibernate5/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy +++ b/grails-datastore-gorm-hibernate5/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy @@ -30,6 +30,8 @@ import org.hibernate.Session import org.hibernate.engine.spi.SessionImplementor import org.hibernate.engine.spi.Status import org.hibernate.persister.entity.EntityPersister +import org.slf4j.Logger +import org.slf4j.LoggerFactory /** * A class to customize Hibernate dirtiness based on Grails {@link DirtyCheckable} interface @@ -42,6 +44,8 @@ import org.hibernate.persister.entity.EntityPersister @CompileStatic class GrailsEntityDirtinessStrategy implements CustomEntityDirtinessStrategy { + protected static final Logger LOG = LoggerFactory.getLogger(GrailsEntityDirtinessStrategy.class) + @Override boolean canDirtyCheck(Object entity, EntityPersister persister, Session session) { return entity instanceof DirtyCheckable @@ -56,6 +60,30 @@ class GrailsEntityDirtinessStrategy implements CustomEntityDirtinessStrategy { void resetDirty(Object entity, EntityPersister persister, Session session) { if (canDirtyCheck(entity, persister, session)) { cast(entity).trackChanges() + try { + PersistentEntity persistentEntity = GormEnhancer.findEntity(Hibernate.getClass(entity)) + if (persistentEntity != null) { + resetDirtyEmbeddedObjects(persistentEntity, entity, persister, session) + } + } catch (IllegalStateException e) { + if (LOG.isDebugEnabled()) { + LOG.debug(e.message, e) + } + } + } + } + + private void resetDirtyEmbeddedObjects(PersistentEntity persistentEntity, + Object entity, + EntityPersister persister, + Session session) { + + if (DirtyCheckingSupport.areEmbeddedDirty(persistentEntity, entity)) { + final associations = persistentEntity.getEmbedded() + for (Embedded a in associations) { + final value = a.reader.read(entity) + resetDirty(value, persister, session) + } } }