如何在 Grails 中检查 isDirty('transient_fieldName') 的瞬态字段
How to check isDirty('transient_fieldName') for transient fields in Grails
在我的一个域 class 中有一个案例,我们在 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)
}
}
为了处理这个问题,我创建了 isDirtyMongo('transient_field')。这在修改非瞬态 属性 之前效果很好,因为 afterUpdate 仅针对瞬态属性调用。
修改后的hook如下:
def afterUpdate() {
if(this.isDirtyMongo("configuration"))
configurationService.save(id, CollectionConstants.RESOURCE_INSTANCE_IDENTIFIER, configuration)
}
boolean isDirtyMongo(String property){
//return whether is dirty or not
}
因此,最终的问题是我们如何为瞬时字段修改调用更新挂钩。
非常感谢任何帮助。
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;
}
}
基本上,如果 transient 字段是脏的,让 Hibernate 认为所有字段都是脏的。
您可以尝试稍微优化一下,仅将第一个 属性 标记为脏(无论其中有多少脏,如果至少有一个 属性 是脏的,则该实体是脏的脏):
int[] result = new int[1];
result[0] = 0;
return result;
但是,如果您对这些实体使用 @DynamicUpdate
,这将始终从 SQL update
语句中排除其他属性,因此我认为更清晰和一致的方法是将所有属性标记为脏(没有 @DynamicUpdate
所有属性总是包含在 SQL update
语句中)。
在我的一个域 class 中有一个案例,我们在 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)
}
}
为了处理这个问题,我创建了 isDirtyMongo('transient_field')。这在修改非瞬态 属性 之前效果很好,因为 afterUpdate 仅针对瞬态属性调用。
修改后的hook如下:
def afterUpdate() {
if(this.isDirtyMongo("configuration"))
configurationService.save(id, CollectionConstants.RESOURCE_INSTANCE_IDENTIFIER, configuration)
}
boolean isDirtyMongo(String property){
//return whether is dirty or not
}
因此,最终的问题是我们如何为瞬时字段修改调用更新挂钩。
非常感谢任何帮助。
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;
}
}
基本上,如果 transient 字段是脏的,让 Hibernate 认为所有字段都是脏的。
您可以尝试稍微优化一下,仅将第一个 属性 标记为脏(无论其中有多少脏,如果至少有一个 属性 是脏的,则该实体是脏的脏):
int[] result = new int[1];
result[0] = 0;
return result;
但是,如果您对这些实体使用 @DynamicUpdate
,这将始终从 SQL update
语句中排除其他属性,因此我认为更清晰和一致的方法是将所有属性标记为脏(没有 @DynamicUpdate
所有属性总是包含在 SQL update
语句中)。