3232
3333import org .springframework .beans .factory .annotation .Value ;
3434import org .springframework .context .ApplicationEvent ;
35+ import org .springframework .util .ReflectionUtils ;
3536
3637import grails .gorm .annotation .AutoTimestamp ;
3738import org .grails .datastore .gorm .timestamp .DefaultTimestampProvider ;
3839import org .grails .datastore .gorm .timestamp .TimestampProvider ;
3940import org .grails .datastore .mapping .config .Entity ;
4041import org .grails .datastore .mapping .config .Settings ;
4142import org .grails .datastore .mapping .core .Datastore ;
43+ import org .grails .datastore .mapping .dirty .checking .DirtyCheckable ;
4244import org .grails .datastore .mapping .engine .EntityAccess ;
4345import org .grails .datastore .mapping .engine .event .AbstractPersistenceEvent ;
4446import org .grails .datastore .mapping .engine .event .AbstractPersistenceEventListener ;
@@ -148,10 +150,25 @@ private void initializeIfNecessary(PersistentEntity entity, String name) {
148150 public boolean beforeUpdate (PersistentEntity entity , EntityAccess ea ) {
149151 Set <String > props = getLastUpdatedPropertyNames (entity .getName ());
150152 if (props != null ) {
153+ Object entityObject = ea .getEntity ();
154+ boolean isDirtyCheckable = entityObject instanceof DirtyCheckable ;
155+
156+ // For dirty-checking datastores (e.g., MongoDB), only set autotimestamp if entity has dirty properties
157+ if (isDirtyCheckable ) {
158+ List <String > dirtyPropertyNames = ((DirtyCheckable ) entityObject ).listDirtyPropertyNames ();
159+ if (dirtyPropertyNames .isEmpty ()) {
160+ return true ;
161+ }
162+ }
163+
151164 for (String prop : props ) {
152165 Class <?> lastUpdateType = ea .getPropertyType (prop );
153166 Object timestamp = timestampProvider .createTimestamp (lastUpdateType );
154167 ea .setProperty (prop , timestamp );
168+ // Mark property as dirty for datastores that use dirty checking (e.g., MongoDB)
169+ if (isDirtyCheckable ) {
170+ ((DirtyCheckable ) entityObject ).markDirty (prop );
171+ }
155172 }
156173 }
157174 return true ;
@@ -167,18 +184,6 @@ protected Set<String> getDateCreatedPropertyNames(String entityName) {
167184 return properties == null ? null : properties .orElse (null );
168185 }
169186
170- private static Field getFieldFromHierarchy (Class <?> entity , String fieldName ) {
171- Class <?> clazz = entity ;
172- while (clazz != null ) {
173- try {
174- return clazz .getDeclaredField (fieldName );
175- } catch (NoSuchFieldException e ) {
176- clazz = clazz .getSuperclass ();
177- }
178- }
179- return null ;
180- }
181-
182187 protected void storeDateCreatedAndLastUpdatedInfo (PersistentEntity persistentEntity ) {
183188 if (persistentEntity .isInitialized ()) {
184189 ClassMapping <?> classMapping = persistentEntity .getMapping ();
@@ -190,13 +195,15 @@ protected void storeDateCreatedAndLastUpdatedInfo(PersistentEntity persistentEnt
190195 } else if (property .getName ().equals (DATE_CREATED_PROPERTY )) {
191196 storeTimestampAvailability (entitiesWithDateCreated , persistentEntity , property );
192197 } else {
193- Field field = getFieldFromHierarchy (persistentEntity .getJavaClass (), property .getName ());
194- if (field != null && field .isAnnotationPresent (AutoTimestamp .class )) {
195- AutoTimestamp autoTimestamp = field .getAnnotation (AutoTimestamp .class );
196- if (autoTimestamp .value () == AutoTimestamp .EventType .UPDATED ) {
197- storeTimestampAvailability (entitiesWithLastUpdated , persistentEntity , property );
198- } else {
199- storeTimestampAvailability (entitiesWithDateCreated , persistentEntity , property );
198+ Field field = ReflectionUtils .findField (persistentEntity .getJavaClass (), property .getName ());
199+ if (field != null ) {
200+ if (field .isAnnotationPresent (AutoTimestamp .class )) {
201+ AutoTimestamp autoTimestamp = field .getAnnotation (AutoTimestamp .class );
202+ if (autoTimestamp .value () == AutoTimestamp .EventType .UPDATED ) {
203+ storeTimestampAvailability (entitiesWithLastUpdated , persistentEntity , property );
204+ } else {
205+ storeTimestampAvailability (entitiesWithDateCreated , persistentEntity , property );
206+ }
200207 }
201208 }
202209 }
0 commit comments