How to check isDirty ('transient_fieldName') for transition fields in Grails

Having a case in one of my domain class, we save the transition field to the Mongo database in hook beforeInsert and afterUpdate, which works fine with the following conditions: -

  • The inserts work great without any problems.
  • Updates work well if there is a modified intransient field

The isDirty task works for non-transient properties.

The code is as follows:

class ResoruceInstance { def configurationService Status status //Transient Map<String, Object> configuration static transients = ['configuration'] public Map<String, Object> getConfiguration() { if(!configuration) configuration = configurationService.get(id, CollectionConstants.RESOURCE_INSTANCE_IDENTIFIER) return configuration } def afterInsert() { configurationService.save(id, CollectionConstants.RESOURCE_INSTANCE_IDENTIFIER, configuration) } def afterUpdate() { if(this.isDirty("configuration")) configurationService.save(id, CollectionConstants.RESOURCE_INSTANCE_IDENTIFIER, configuration) } } 

To deal with this problem, I created isDirtyMongo ('transient_field'). This works well until the non-transient property changes, since afterUpdate is called only for transient properties.

The modified hook is as follows:

 def afterUpdate() { if(this.isDirtyMongo("configuration")) configurationService.save(id, CollectionConstants.RESOURCE_INSTANCE_IDENTIFIER, configuration) } boolean isDirtyMongo(String property){ //return whether is dirty or not } 

So, the final question is how can we also call the update hook for the transition field changes.

Any help would be greatly appreciated.

+6
source share
1 answer

Add Interceptor.findDirty :

 public class TransientFieldDirtinessInterceptor extends EmptyInterceptor { @Override public int[] findDirty(Object entity, ..., String[] propertyNames, ...) { if ((entity instanceof EntityToCheck) && isTransientFieldDirty(entity)) { // Just return all fields as dirty int[] result = new int[propertyNames.length]; for(int i = 0; i < result.length; i++) { result[i] = i; } return result; } // Use Hibernate default dirty-checking algorithm return null; } } 

Basically, let Hibernate consider that all fields are dirty if the transient field is dirty.

You can try to optimize this a bit to mark only the first property as dirty (no matter how many of them are dirty, the object is dirty if at least one property is dirty):

 int[] result = new int[1]; result[0] = 0; return result; 

However, this always excludes other properties from the SQL update statement if you use @DynamicUpdate for these objects, so I suggest that a more understandable and consistent way is to mark all properties as dirty (without @DynamicUpdate all properties are always included in the SQL update statement).

+1
source

Source: https://habr.com/ru/post/989502/


All Articles