如何检查Grails中瞬态字段的isDirty('transient_fieldName')

Vin*_*ati 6 orm grails hibernate grails-orm

在我的一个域类中有一个案例,我们在beforeInsert和afterUpdate挂钩中将一个瞬态字段存储到Mongo数据库,它完全适用于以下条件: -

  • 插件运行良好,没有任何问题.
  • 如果存在修改的非瞬态字段,则更新很有效

问题是isDirty适用于非瞬态属性.

代码如下:

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)
     }

}
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,我创建了isDirtyMongo('transient_field').这非常有效,直到修改非瞬态属性为止,因为仅为瞬态属性调用afterUpdate.

修改后的钩子如下:

def afterUpdate() {
            if(this.isDirtyMongo("configuration"))
                configurationService.save(id, CollectionConstants.RESOURCE_INSTANCE_IDENTIFIER, configuration)
         }

boolean isDirtyMongo(String property){
//return whether is dirty or not
}
Run Code Online (Sandbox Code Playgroud)

因此,最终的问题是我们如何调用瞬态场修改的更新钩子.

任何帮助将受到高度赞赏.

Dra*_*vic 1

实现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's default dirty-checking algorithm
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,如果瞬态字段是脏的,那么让 Hibernate 认为所有字段都是脏的。

您可以尝试稍微优化一下,仅将第一个属性标记为脏(无论其中有多少个属性是脏的,如果至少有一个属性是脏的,则该实体是脏的):

int[] result = new int[1];
result[0] = 0;
return result;
Run Code Online (Sandbox Code Playgroud)

update但是,如果您用于这些实体,这将始终从 SQL 语句中排除其他属性@DynamicUpdate,因此我认为更清晰和一致的方法是将所有属性标记为脏(无论如何,@DynamicUpdate所有属性都始终包含在 SQLupdate语句中)。