Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class GrailsEntityDirtinessStrategy implements CustomEntityDirtinessStrategy {

@Override
boolean isDirty(Object entity, EntityPersister persister, Session session) {
!session.contains(entity) || !cast(entity).listDirtyPropertyNames().isEmpty() || DirtyCheckingSupport.areEmbeddedDirty(GormEnhancer.findEntity(Hibernate.getClass(entity)), entity)
!session.contains(entity) || cast(entity).hasChanged() || DirtyCheckingSupport.areEmbeddedDirty(GormEnhancer.findEntity(Hibernate.getClass(entity)), entity)
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public void setEventPublisher(ConfigurableApplicationEventPublisher eventPublish
public void onSaveOrUpdate(SaveOrUpdateEvent hibernateEvent) throws HibernateException {
Object entity = getEntity(hibernateEvent);
if(entity != null && proxyHandler.isInitialized(entity)) {
activateDirtyChecking(entity);
org.grails.datastore.mapping.engine.event.SaveOrUpdateEvent grailsEvent = new org.grails.datastore.mapping.engine.event.SaveOrUpdateEvent(
this.datastore, entity);
publishEvent(hibernateEvent, grailsEvent);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package grails.gorm.tests.dirtychecking

import grails.gorm.transactions.Rollback
import org.grails.datastore.gorm.events.ConfigurableApplicationEventPublisher
import org.grails.datastore.mapping.core.Datastore
import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent
import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
import org.grails.datastore.mapping.engine.event.PreInsertEvent
import org.grails.datastore.mapping.engine.event.PreUpdateEvent
import org.grails.orm.hibernate.HibernateDatastore
import org.springframework.context.ApplicationEvent
import org.springframework.context.ApplicationEventPublisher
import org.springframework.context.ConfigurableApplicationContext
import org.springframework.transaction.PlatformTransactionManager
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification
import spock.util.concurrent.PollingConditions

class HibernateUpdateFromListenerSpec extends Specification {

@Shared
@AutoCleanup
HibernateDatastore datastore = new HibernateDatastore(Person)
@Shared PlatformTransactionManager transactionManager = datastore.transactionManager

PersonSaveOrUpdatePersistentEventListener listener

void setup() {
listener = new PersonSaveOrUpdatePersistentEventListener(datastore)
ApplicationEventPublisher publisher = datastore.applicationEventPublisher
if (publisher instanceof ConfigurableApplicationEventPublisher) {
((ConfigurableApplicationEventPublisher) publisher).addApplicationListener(listener)
} else if (publisher instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) publisher).addApplicationListener(listener)
}
}

@Rollback
void "test the changes made from the listener are saved"() {
when:
Person danny = new Person(name: "Danny", occupation: "manager").save()

then:
new PollingConditions().eventually {listener.isExecuted && Person.count()}

when:
datastore.currentSession.flush()
datastore.currentSession.clear()
danny = Person.get(danny.id)

then:
danny.occupation
danny.occupation.endsWith("listener")
}

static class PersonSaveOrUpdatePersistentEventListener extends AbstractPersistenceEventListener {

boolean isExecuted

protected PersonSaveOrUpdatePersistentEventListener(Datastore datastore) {
super(datastore)
}

@Override
protected void onPersistenceEvent(AbstractPersistenceEvent event) {
if (event.entityObject instanceof Person) {
Person person = (Person) event.entityObject
person.occupation = person.occupation + " listener"
}
isExecuted = true
}

@Override
boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return eventType == PreUpdateEvent || eventType == PreInsertEvent
}
}
}