From 5ad8e7ead46706a35d6d79207f8f283d7f46825e Mon Sep 17 00:00:00 2001 From: rbygrave Date: Thu, 29 Jul 2021 12:47:10 +1200 Subject: [PATCH] Use new @DbJson dirtyDetection and keepSource attributes - Bump ebean-annotation with new @DbJson dirtyDetection and keepSource attributes - Get those to BeanPropertyJsonMapper to chose MutableHash implementation - Modify MD5MutableHash to include check for isDirty() - EBasicJsonList needs keepSource=true to pass that test with oldValue --- ebean-api/pom.xml | 2 +- .../server/deploy/BeanPropertyJsonMapper.java | 36 ++++++++++++++++--- .../deploy/meta/DeployBeanProperty.java | 21 +++++++++++ .../server/deploy/parse/DeployUtil.java | 9 +++-- .../type/ScalarTypeJsonObjectMapper.java | 4 --- .../org/tests/model/json/EBasicJsonList.java | 2 +- 6 files changed, 58 insertions(+), 16 deletions(-) diff --git a/ebean-api/pom.xml b/ebean-api/pom.xml index d3868ff91..649f85822 100644 --- a/ebean-api/pom.xml +++ b/ebean-api/pom.xml @@ -50,7 +50,7 @@ io.ebean ebean-annotation - 7.0 + 7.1 diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyJsonMapper.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyJsonMapper.java index 40c90d853..c7fba7b8b 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyJsonMapper.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyJsonMapper.java @@ -15,16 +15,24 @@ import java.util.Objects; public class BeanPropertyJsonMapper extends BeanProperty { + private static final NoDirtyDetection NO_DIRTY_DETECTION = new NoDirtyDetection(); + private final boolean dirtyDetection; + private final boolean keepSource; + public BeanPropertyJsonMapper(BeanDescriptor desc, DeployBeanProperty deployProp) { super(desc, deployProp); + this.dirtyDetection = deployProp.isDirtyDetection(); + this.keepSource = deployProp.isKeepSource(); } @Override public MutableHash createMutableHash(String json) { - if (false) { // TODO should we make that configurable? - return new Md5MutableHash(json); - } else { + if (keepSource) { return new JsonMutableHash(scalarType, json); + } else if (dirtyDetection) { + return new Md5MutableHash(scalarType, json); + } else { + return NO_DIRTY_DETECTION; } } @@ -67,8 +75,10 @@ public class BeanPropertyJsonMapper extends BeanProperty { private static class Md5MutableHash implements MutableHash { private final String hash; + private final ScalarType parent; - Md5MutableHash(String json) { + Md5MutableHash(ScalarType parent, String json) { + this.parent = parent; this.hash = hash(json); } @@ -78,7 +88,7 @@ public class BeanPropertyJsonMapper extends BeanProperty { @Override public boolean isEqualToObject(Object obj) { - return true; // we cannot determine differences... + return isEqualToJson(parent.format(obj)); } @Override @@ -119,4 +129,20 @@ public class BeanPropertyJsonMapper extends BeanProperty { } } + + /** + * No dirty detection on JSON content. + */ + private static class NoDirtyDetection implements MutableHash { + + @Override + public boolean isEqualToJson(String json) { + return true; + } + + @Override + public boolean isEqualToObject(Object obj) { + return true; + } + } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java index 92ad7f1e9..060ce802f 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java @@ -109,6 +109,8 @@ public class DeployBeanProperty { private boolean jsonSerialize = true; private boolean jsonDeserialize = true; + private boolean dirtyDetection; + private boolean keepSource; private boolean dbEncrypted; private DbEncryptFunction dbEncryptFunction; @@ -327,6 +329,20 @@ public class DeployBeanProperty { this.jsonDeserialize = jsonDeserialize; } + /** + * Return true if we should have JSON dirty detection on this property. + */ + public boolean isDirtyDetection() { + return dirtyDetection; + } + + /** + * Return true if we should store source JSON content on this property. + */ + public boolean isKeepSource() { + return keepSource; + } + /** * Return the sortOrder for the properties. */ @@ -1204,4 +1220,9 @@ public class DeployBeanProperty { boolean isJsonMapper() { return scalarType != null && scalarType.isJsonMapper(); } + + public void setJsonOptions(boolean dirtyDetection, boolean keepSource) { + this.dirtyDetection = dirtyDetection; + this.keepSource = keepSource; + } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/DeployUtil.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/DeployUtil.java index 65c7cf45e..2245b0c4c 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/DeployUtil.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/DeployUtil.java @@ -213,23 +213,22 @@ public class DeployUtil { * This property is marked as a Lob object. */ void setDbJsonType(DeployBeanProperty prop, DbJson dbJsonType) { - int dbType = getDbJsonStorage(dbJsonType.storage()); - setDbJsonType(prop, dbType, dbJsonType.length()); + setDbJsonType(prop, dbType, dbJsonType.length(), dbJsonType.dirtyDetection(), dbJsonType.keepSource()); } void setDbJsonBType(DeployBeanProperty prop, DbJsonB dbJsonB) { - setDbJsonType(prop, DbPlatformType.JSONB, dbJsonB.length()); + setDbJsonType(prop, DbPlatformType.JSONB, dbJsonB.length(), dbJsonB.dirtyDetection(), dbJsonB.keepSource()); } - private void setDbJsonType(DeployBeanProperty prop, int dbType, int dbLength) { - + private void setDbJsonType(DeployBeanProperty prop, int dbType, int dbLength, boolean dirtyDetection, boolean keepSource) { ScalarType scalarType = typeManager.getJsonScalarType(prop, dbType, dbLength); if (scalarType == null) { throw new RuntimeException("No ScalarType for JSON property [" + prop + "] [" + dbType + "]"); } prop.setDbType(dbType); prop.setScalarType(scalarType); + prop.setJsonOptions(dirtyDetection, keepSource); if (dbType == Types.VARCHAR || dbLength > 0) { // determine the db column size int columnLength = (dbLength > 0) ? dbLength : DEFAULT_JSON_VARCHAR_LENGTH; diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonObjectMapper.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonObjectMapper.java index 2c3be2fa3..14425c6c9 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonObjectMapper.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonObjectMapper.java @@ -7,8 +7,6 @@ import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.introspect.AnnotatedField; - -import io.ebean.bean.MutableHash; import io.ebean.core.type.DataBinder; import io.ebean.core.type.DataReader; import io.ebean.core.type.DocPropertyType; @@ -17,7 +15,6 @@ import io.ebean.text.TextException; import io.ebeaninternal.json.ModifyAwareList; import io.ebeaninternal.json.ModifyAwareMap; import io.ebeaninternal.json.ModifyAwareSet; -import io.ebeaninternal.server.util.Md5; import javax.persistence.PersistenceException; import java.io.DataInput; @@ -27,7 +24,6 @@ import java.sql.SQLException; import java.sql.Types; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; /** diff --git a/ebean-core/src/test/java/org/tests/model/json/EBasicJsonList.java b/ebean-core/src/test/java/org/tests/model/json/EBasicJsonList.java index 22b32e3e1..05d9807b5 100644 --- a/ebean-core/src/test/java/org/tests/model/json/EBasicJsonList.java +++ b/ebean-core/src/test/java/org/tests/model/json/EBasicJsonList.java @@ -31,7 +31,7 @@ public class EBasicJsonList { @DbJson(length = 700) Map beanMap = new LinkedHashMap<>(); - @DbJson(length = 500) + @DbJson(length = 500, keepSource = true) // such that we can rebuild old values PlainBean plainBean; @DbJson(length = 50)