Add BeanPropertyJsonMapper for JSON dirty detection

This commit is contained in:
rbygrave
2021-07-28 21:43:57 +12:00
parent 6c262f1df5
commit 11eed4cfe9
4 changed files with 64 additions and 31 deletions
@@ -219,7 +219,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
*/
@SuppressWarnings("rawtypes")
final ScalarType scalarType;
final boolean jsonMapperType;
private final DocPropertyOptions docOptions;
@@ -333,7 +332,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
this.formula = sqlFormulaSelect != null;
this.dbType = deploy.getDbType();
this.scalarType = deploy.getScalarType();
this.jsonMapperType = (scalarType == null) ? false : scalarType.isJsonMapper();
this.lob = isLobType(dbType);
this.propertyType = deploy.getPropertyType();
this.field = deploy.getField();
@@ -428,7 +426,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
this.setter = source.setter;
this.dbType = source.getDbType(true);
this.scalarType = source.scalarType;
this.jsonMapperType = source.jsonMapperType;
this.lob = isLobType(dbType);
this.propertyType = source.getPropertyType();
this.field = source.getField();
@@ -632,13 +629,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
Object value = scalarType.read(reader);
if (bean != null) {
setValue(bean, value);
if (jsonMapperType) {
String json = reader.popJson();
if (json != null) {
final String hash = Md5.hash(json);
bean._ebean_getIntercept().mutableHash(propertyIndex, hash);
}
}
}
return value;
} catch (TextException e) {
@@ -1028,18 +1018,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
* This is only used for 'mutable' scalar types like hstore etc.
*/
boolean isDirtyValue(Object value, EntityBeanIntercept ebi) {
if (jsonMapperType) {
// dirty detection based on md5 hash of json content
final String json = scalarType.jsonMapper(value);
final String newHash = Md5.hash(json);
final String oldHash = ebi.mutableHash(propertyIndex);
if (!Objects.equals(newHash, oldHash)) {
ebi.mutableContent(propertyIndex, json); // so we only convert to json once
ebi.mutableHash(propertyIndex, newHash); // for dirty detection next time
return true;
}
return false;
}
return scalarType.isDirty(value);
}
@@ -0,0 +1,57 @@
package io.ebeaninternal.server.deploy;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.core.type.DataReader;
import io.ebean.text.TextException;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import io.ebeaninternal.server.util.Md5;
import javax.persistence.PersistenceException;
import java.sql.SQLException;
import java.util.Objects;
public class BeanPropertyJsonMapper extends BeanProperty {
public BeanPropertyJsonMapper(BeanDescriptor<?> desc, DeployBeanProperty deployProp) {
super(desc, deployProp);
}
/**
* Return true if the mutable value is considered dirty.
* This is only used for 'mutable' scalar types like hstore etc.
*/
@Override
boolean isDirtyValue(Object value, EntityBeanIntercept ebi) {
// dirty detection based on md5 hash of json content
final String json = scalarType.jsonMapper(value);
final String newHash = Md5.hash(json);
final String oldHash = ebi.mutableHash(propertyIndex);
if (!Objects.equals(newHash, oldHash)) {
ebi.mutableContent(propertyIndex, json); // so we only convert to json once
ebi.mutableHash(propertyIndex, newHash); // for dirty detection next time
return true;
}
return false;
}
@Override
public Object readSet(DataReader reader, EntityBean bean) throws SQLException {
try {
Object value = scalarType.read(reader);
if (bean != null) {
setValue(bean, value);
String json = reader.popJson();
if (json != null) {
final String hash = Md5.hash(json);
bean._ebean_getIntercept().mutableHash(propertyIndex, hash);
}
}
return value;
} catch (TextException e) {
throw e;
} catch (Exception e) {
throw new PersistenceException("Error readSet on " + descriptor + "." + name, e);
}
}
}
@@ -1201,4 +1201,7 @@ public class DeployBeanProperty {
return false;
}
boolean isJsonMapper() {
return scalarType != null && scalarType.isJsonMapper();
}
}
@@ -1,15 +1,7 @@
package io.ebeaninternal.server.deploy.meta;
import io.ebean.bean.EntityBean;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanDescriptorMap;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import io.ebeaninternal.server.deploy.BeanPropertyIdClass;
import io.ebeaninternal.server.deploy.BeanPropertyOrderColumn;
import io.ebeaninternal.server.deploy.BeanPropertySimpleCollection;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.deploy.*;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import io.ebeaninternal.server.properties.BeanPropertySetter;
import io.ebeaninternal.server.type.ScalarTypeString;
@@ -490,6 +482,9 @@ public class DeployBeanPropertyLists {
return new BeanPropertyAssocMany(desc, (DeployBeanPropertyAssocMany) deployProp);
}
if (deployProp.isJsonMapper()) {
return new BeanPropertyJsonMapper(desc, deployProp);
}
return new BeanProperty(desc, deployProp);
}