some refactor and tidying

This commit is contained in:
Roland Praml committed 2021-07-28 17:22:29 +02:00
1 parent 5e595ec5f8
commit b497b8635b
12 files changed
+184 -107

No files matched your search

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonToken;
import io.ebean.ValuePair;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.MutableHash;
import io.ebean.bean.PersistenceContext;
import io.ebean.config.EncryptKey;
import io.ebean.config.dbplatform.DbEncryptFunction;
@@ -818,6 +819,13 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
public Object parse(String value) {
return scalarType.parse(value);
}
/**
* creates a mutableHash for the given JSON value.
*/
public MutableHash createMutableHash(String json) {
return scalarType.createMutableHash(json);
}
/**
* Read the value for this property from L2 cache entry and set it to the bean.
@@ -2,15 +2,13 @@ package io.ebeaninternal.server.deploy;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.MutableJson;
import io.ebean.bean.MutableHash;
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 {
@@ -26,11 +24,9 @@ public class BeanPropertyJsonMapper extends BeanProperty {
boolean isDirtyValue(Object value, EntityBeanIntercept ebi) {
// dirty detection based on md5 hash of json content
final String json = scalarType.jsonMapper(value);
final MutableJson oldHash = ebi.mutableHash(propertyIndex);
final MutableHash oldHash = ebi.mutableHash(propertyIndex);
if (oldHash == null || !oldHash.isEqualToJson(json)) {
ebi.mutableContent(propertyIndex, json); // so we only convert to json once
//ebi.mutableHash(propertyIndex, scalarType.jsonMutable(json)); // for dirty detection next time
//must be done AFTER persistControllers are called.
return true;
}
return false;
@@ -44,8 +40,8 @@ public class BeanPropertyJsonMapper extends BeanProperty {
setValue(bean, value);
String json = reader.popJson();
if (json != null) {
final String hash = scalarType.format(value);
bean._ebean_getIntercept().mutableHash(propertyIndex, scalarType.jsonMutable(hash));
final MutableHash hash = scalarType.createMutableHash(json);
bean._ebean_getIntercept().mutableHash(propertyIndex, hash);
}
}
return value;
@@ -1,8 +1,8 @@
package io.ebeaninternal.server.persist.dmlbind;
import io.ebean.bean.EntityBean;
import io.ebean.bean.MutableHash;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.util.Md5;
import java.sql.SQLException;
@@ -30,9 +30,10 @@ class BindablePropertyJsonInsert extends BindableProperty {
if (value == null) {
request.bind(null, prop);
} else {
// on insert store MD5 hash and push json
// on insert store hash and push json
final String json = prop.format(value);
bean._ebean_getIntercept().mutableHash(propertyIndex, prop.getScalarType().jsonMutable(json));
final MutableHash hash = prop.createMutableHash(json);
bean._ebean_getIntercept().mutableHash(propertyIndex, hash);
request.pushJson(json);
request.bind(value, prop);
}
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.persist.dmlbind;
import io.ebean.bean.EntityBean;
import io.ebean.bean.MutableHash;
import io.ebeaninternal.server.deploy.BeanProperty;
import java.sql.SQLException;
@@ -25,8 +26,10 @@ class BindablePropertyJsonUpdate extends BindableProperty {
if (bean == null) {
request.bind(null, prop);
} else {
// on update push json
// on update store hash and push json
final String json = bean._ebean_getIntercept().mutableContent(propertyIndex);
final MutableHash hash = prop.createMutableHash(json);
bean._ebean_getIntercept().mutableHash(propertyIndex, hash);
request.pushJson(json);
final Object value = prop.getValue(bean);
request.bind(value, prop);
@@ -46,12 +46,15 @@ public class DataBind implements DataBinder {
@Override
public void pushJson(String json) {
assert this.json == null; // we can only push one value
this.json = json;
}
@Override
public String popJson() {
return json;
String ret = json;
json = null;
return ret;
}
@Override
@@ -8,7 +8,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import io.ebean.bean.MutableJson;
import io.ebean.bean.MutableHash;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -51,7 +51,59 @@ class ScalarTypeJsonObjectMapper {
}
return new GenericObject(jsonManager, field, dbType, type);
}
private static class Md5MutableHash implements MutableHash {
private final String md5;
Md5MutableHash(String json) {
md5 = Md5.hash(json);
}
@Override
public boolean isEqualToObject(Object obj) {
return true; // we cannot determine differences...
}
@Override
public boolean isEqualToJson(String json) {
return Md5.hash(json).equals(md5);
}
@Override
public Object get() {
return null; // cannot create object from json
}
}
private static class JsonMutableHash implements MutableHash {
private final String originalJson;
private ScalarType<?> parent;
JsonMutableHash(ScalarType<?> parent, String json) {
this.parent = parent;
originalJson = json;
}
@Override
public boolean isEqualToObject(Object obj) {
return isEqualToJson(parent.format(obj));
}
@Override
public boolean isEqualToJson(String json) {
return Objects.equals(originalJson, json);
}
@Override
public Object get() {
return parent.parse(originalJson);
}
}
/**
* Maps any type (Object) using Jackson ObjectMapper.
*/
@@ -71,63 +123,16 @@ class ScalarTypeJsonObjectMapper {
return formatValue(value);
}
private class Md5MutableJson implements MutableJson {
private String md5;
Md5MutableJson(String json) {
md5 = Md5.hash(json);
}
@Override
public boolean isEqualToObject(Object obj) {
return true; // we cannot determine differences...
}
@Override
public boolean isEqualToJson(String json) {
return Md5.hash(json).equals(md5);
}
@Override
public Object get() {
return null; // cannot create object from json
}
@Override
public void update(Object obj) {
md5 = Md5.hash(format(obj));
}
}
private class PlainMutableJson implements MutableJson {
private String originalJson;
PlainMutableJson(String json) {
originalJson = json;
}
@Override
public boolean isEqualToObject(Object obj) {
return isEqualToJson(format(obj));
}
@Override
public boolean isEqualToJson(String json) {
return Objects.equals(originalJson, json);
}
@Override
public Object get() {
return parse(originalJson);
}
@Override
public void update(Object obj) {
originalJson = format(obj);
}
}
@Override
public MutableJson jsonMutable(String originalJson) {
if (false) {
return new Md5MutableJson(originalJson);
public MutableHash createMutableHash(String json) {
if (false) { // TODO should we make that configurable?
return new Md5MutableHash(json);
} else {
return new PlainMutableJson(originalJson);
return new JsonMutableHash(this, json);
}
}
@@ -50,6 +50,7 @@ public class TestDbJson_Jackson3 extends BaseTestCase {
EBasicJsonJackson3 bean = new EBasicJsonJackson3();
bean.setName("b1");
bean.setPlainValue(contentBean);
bean.setPlainValue2(contentBean);
bean.save();
@@ -121,10 +122,11 @@ public class TestDbJson_Jackson3 extends BaseTestCase {
.containsExactlyInAnyOrder("beanList=null,[name:a]","name=p1-mod,p1","version=2,1");
found.getPlainBean().setName("b");
assertThat(DB.getBeanState(found).isDirty()).isFalse();
// CHECKME: How do we get these checks to work?
// assertThat(DB.getBeanState(found).isDirty()).isTrue();
found.getPlainBean().setName("b");
assertThat(DB.getBeanState(found).isDirty()).isTrue();
state = DB.getBeanState(found);
assertThat(state.getChangedProps()).containsExactlyInAnyOrder("plainBean");
@@ -145,4 +147,24 @@ public class TestDbJson_Jackson3 extends BaseTestCase {
.extracting(Map.Entry::toString)
.containsExactlyInAnyOrder("plainBean=name:b,name:a", "version=3,2");
}
@Test
public void updateIncludesJsonColumn_when_list_loadedAndNotDirtyAware() {
PlainBean contentBean = new PlainBean("a", 42);
EBasicJsonList bean = new EBasicJsonList();
bean.setName("p1");
bean.setPlainBean(contentBean);
bean.setBeanList(Arrays.asList(contentBean));
DB.save(bean);
final EBasicJsonList found = DB.find(EBasicJsonList.class, bean.getId());
found.getBeanList().get(0).setName("p1-mod");
BeanState state = DB.getBeanState(found);
assertThat(state.getChangedProps()).containsExactlyInAnyOrder("beanList");
// this test fails, because we have a OmList instead of a GenericObject
// TODO: Can/Should we enhance the @DbJson/@DbJsonB annotations with a property "dirtyDetection"
}
}
@@ -18,6 +18,9 @@ public class EBasicJsonJackson3 extends Model {
@DbJson(length = 500)
PlainBeanDirtyAware plainValue;
@DbJson(length = 500)
PlainBeanDirtyAware plainValue2;
@Version
long version;
@@ -45,6 +48,14 @@ public class EBasicJsonJackson3 extends Model {
this.plainValue = plainValue;
}
public PlainBeanDirtyAware getPlainValue2() {
return plainValue2;
}
public void setPlainValue2(PlainBeanDirtyAware plainValue2) {
this.plainValue2 = plainValue2;
}
public long getVersion() {
return version;
}