mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Merge branch 'master' of github.com:ebean-orm/ebean
This commit is contained in:
@@ -223,6 +223,8 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
private short profileId;
|
||||
|
||||
private Object jacksonAnnotatedClass;
|
||||
|
||||
/**
|
||||
* Construct the BeanDescriptor.
|
||||
*/
|
||||
@@ -1238,6 +1240,7 @@ public class DeployBeanDescriptor<T> {
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeployWord(String expression) {
|
||||
return descriptor.getDeployWord(expression);
|
||||
}
|
||||
@@ -1252,4 +1255,16 @@ public class DeployBeanDescriptor<T> {
|
||||
return (property == null) ? null : "${ta}." + property.getDbColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the jackson annotated class, if jackson is present.
|
||||
*/
|
||||
public Object /*AnnotatedClass*/ getJacksonAnnotatedClass() {
|
||||
if (jacksonAnnotatedClass == null) {
|
||||
com.fasterxml.jackson.databind.ObjectMapper objectMapper = (com.fasterxml.jackson.databind.ObjectMapper) serverConfig.getObjectMapper();
|
||||
com.fasterxml.jackson.databind.JavaType javaType = objectMapper.getTypeFactory().constructType(beanType);
|
||||
jacksonAnnotatedClass = com.fasterxml.jackson.databind.introspect.AnnotatedClassResolver
|
||||
.resolve(objectMapper.getDeserializationConfig(), javaType, objectMapper.getDeserializationConfig());
|
||||
}
|
||||
return jacksonAnnotatedClass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1124,4 +1124,18 @@ public class DeployBeanProperty {
|
||||
public void setElementProperty() {
|
||||
this.elementProperty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the jackson annotated field, if jackson is present.
|
||||
*/
|
||||
public Object /*AnnotatedField*/ getJacksonField() {
|
||||
com.fasterxml.jackson.databind.introspect.AnnotatedClass jac =
|
||||
(com.fasterxml.jackson.databind.introspect.AnnotatedClass) getDesc().getJacksonAnnotatedClass();
|
||||
for (com.fasterxml.jackson.databind.introspect.AnnotatedField candidate : jac.fields()) {
|
||||
if (candidate.getName().equals(getName())) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,10 +239,9 @@ public class DeployUtil {
|
||||
|
||||
private void setDbJsonType(DeployBeanProperty prop, int dbType, int dbLength) {
|
||||
|
||||
Class<?> type = prop.getPropertyType();
|
||||
ScalarType<?> scalarType = typeManager.getJsonScalarType(type, dbType, dbLength, prop.getGenericType());
|
||||
ScalarType<?> scalarType = typeManager.getJsonScalarType(prop, dbType, dbLength);
|
||||
if (scalarType == null) {
|
||||
throw new RuntimeException("No ScalarType for JSON type [" + type + "] [" + dbType + "]");
|
||||
throw new RuntimeException("No ScalarType for JSON property [" + prop + "] [" + dbType + "]");
|
||||
}
|
||||
prop.setDbType(dbType);
|
||||
prop.setScalarType(scalarType);
|
||||
|
||||
@@ -2,6 +2,8 @@ package io.ebeaninternal.server.type;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
|
||||
|
||||
import io.ebean.annotation.DbArray;
|
||||
import io.ebean.annotation.DbEnumType;
|
||||
import io.ebean.annotation.DbEnumValue;
|
||||
@@ -17,6 +19,7 @@ import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.api.ExtraTypeFactory;
|
||||
import io.ebeaninternal.dbmigration.DbOffline;
|
||||
import io.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
@@ -379,31 +382,36 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> getJsonScalarType(Class<?> type, int dbType, int dbLength, Type genericType) {
|
||||
public ScalarType<?> getJsonScalarType(DeployBeanProperty prop, int dbType, int dbLength) {
|
||||
|
||||
Class<?> type = prop.getPropertyType();
|
||||
Type genericType = prop.getGenericType();
|
||||
|
||||
boolean hasJacksonAnnotations = objectMapperPresent && checkJacksonAnnotations(prop);
|
||||
|
||||
if (type.equals(List.class)) {
|
||||
DocPropertyType docType = getDocType(genericType);
|
||||
if (isValueTypeSimple(genericType)) {
|
||||
if (!hasJacksonAnnotations && isValueTypeSimple(genericType)) {
|
||||
return ScalarTypeJsonList.typeFor(postgres, dbType, docType);
|
||||
} else {
|
||||
return createJsonObjectMapperType(type, genericType, dbType, docType);
|
||||
return createJsonObjectMapperType(prop, dbType, docType);
|
||||
}
|
||||
}
|
||||
|
||||
if (type.equals(Set.class)) {
|
||||
DocPropertyType docType = getDocType(genericType);
|
||||
if (isValueTypeSimple(genericType)) {
|
||||
if (!hasJacksonAnnotations && isValueTypeSimple(genericType)) {
|
||||
return ScalarTypeJsonSet.typeFor(postgres, dbType, docType);
|
||||
} else {
|
||||
return createJsonObjectMapperType(type, genericType, dbType, docType);
|
||||
return createJsonObjectMapperType(prop, dbType, docType);
|
||||
}
|
||||
}
|
||||
|
||||
if (type.equals(Map.class)) {
|
||||
if (isMapValueTypeObject(genericType)) {
|
||||
if (!hasJacksonAnnotations && isMapValueTypeObject(genericType)) {
|
||||
return ScalarTypeJsonMap.typeFor(postgres, dbType);
|
||||
} else {
|
||||
return createJsonObjectMapperType(type, genericType, dbType, DocPropertyType.OBJECT);
|
||||
return createJsonObjectMapperType(prop, dbType, DocPropertyType.OBJECT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,7 +434,15 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
}
|
||||
|
||||
return createJsonObjectMapperType(type, type, dbType, DocPropertyType.OBJECT);
|
||||
return createJsonObjectMapperType(prop, dbType, DocPropertyType.OBJECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE, if there is any jackson annotation on that property. All jackson annotations
|
||||
* are annotated with the @JacksonAnnotation meta annotation. So detection is easy.
|
||||
*/
|
||||
private boolean checkJacksonAnnotations(DeployBeanProperty prop) {
|
||||
return AnnotationUtil.findAnnotation(prop.getField(), com.fasterxml.jackson.annotation.JacksonAnnotation.class) != null;
|
||||
}
|
||||
|
||||
private DocPropertyType getDocType(Type genericType) {
|
||||
@@ -459,11 +475,12 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
return Object.class.equals(typeArgs[1]) || "?".equals(typeArgs[1].toString());
|
||||
}
|
||||
|
||||
private ScalarType<?> createJsonObjectMapperType(Class<?> type, Type genericType, int dbType, DocPropertyType docType) {
|
||||
private ScalarType<?> createJsonObjectMapperType(DeployBeanProperty prop, int dbType, DocPropertyType docType) {
|
||||
Class<?> type = prop.getPropertyType();
|
||||
if (objectMapper == null) {
|
||||
throw new IllegalArgumentException("Type [" + type + "] unsupported for @DbJson mapping - Jackson ObjectMapper not present");
|
||||
}
|
||||
return ScalarTypeJsonObjectMapper.createTypeFor(postgres, type, (ObjectMapper) objectMapper, genericType, dbType, docType);
|
||||
return ScalarTypeJsonObjectMapper.createTypeFor(postgres, (AnnotatedField) prop.getJacksonField(), (ObjectMapper) objectMapper, dbType, docType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,14 +9,19 @@ import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.AnnotationIntrospector;
|
||||
import com.fasterxml.jackson.databind.DeserializationConfig;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.List;
|
||||
@@ -31,20 +36,21 @@ public class ScalarTypeJsonObjectMapper {
|
||||
/**
|
||||
* Create and return the appropriate ScalarType.
|
||||
*/
|
||||
public static ScalarType<?> createTypeFor(boolean postgres, Class<?> type, ObjectMapper objectMapper,
|
||||
Type genericType, int dbType, DocPropertyType docType) {
|
||||
public static ScalarType<?> createTypeFor(boolean postgres, AnnotatedField field, ObjectMapper objectMapper,
|
||||
int dbType, DocPropertyType docType) {
|
||||
|
||||
Class<?> type = field.getRawType();
|
||||
String pgType = getPostgresType(postgres, dbType);
|
||||
if (Set.class.equals(type)) {
|
||||
return new OmSet(objectMapper, genericType, dbType, pgType, docType);
|
||||
return new OmSet(objectMapper, field, dbType, pgType, docType);
|
||||
}
|
||||
if (List.class.equals(type)) {
|
||||
return new OmList(objectMapper, genericType, dbType, pgType, docType);
|
||||
return new OmList(objectMapper, field, dbType, pgType, docType);
|
||||
}
|
||||
if (Map.class.equals(type)) {
|
||||
return new OmMap(objectMapper, genericType, dbType, pgType);
|
||||
return new OmMap(objectMapper, field, dbType, pgType);
|
||||
}
|
||||
return new GenericObject(objectMapper, genericType, dbType, pgType);
|
||||
return new GenericObject(objectMapper, field, dbType, pgType);
|
||||
}
|
||||
|
||||
private static String getPostgresType(boolean postgres, int dbType) {
|
||||
@@ -64,8 +70,8 @@ public class ScalarTypeJsonObjectMapper {
|
||||
*/
|
||||
private static class GenericObject extends Base<Object> {
|
||||
|
||||
public GenericObject(ObjectMapper objectMapper, Type type, int dbType, String pgType) {
|
||||
super(Object.class, objectMapper, type, dbType, pgType, DocPropertyType.OBJECT);
|
||||
public GenericObject(ObjectMapper objectMapper, AnnotatedField field, int dbType, String pgType) {
|
||||
super(Object.class, objectMapper, field, dbType, pgType, DocPropertyType.OBJECT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,8 +81,8 @@ public class ScalarTypeJsonObjectMapper {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class OmSet extends Base<Set> {
|
||||
|
||||
public OmSet(ObjectMapper objectMapper, Type type, int dbType, String pgType, DocPropertyType docType) {
|
||||
super(Set.class, objectMapper, type, dbType, pgType, docType);
|
||||
public OmSet(ObjectMapper objectMapper, AnnotatedField field, int dbType, String pgType, DocPropertyType docType) {
|
||||
super(Set.class, objectMapper, field, dbType, pgType, docType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,8 +99,8 @@ public class ScalarTypeJsonObjectMapper {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class OmList extends Base<List> {
|
||||
|
||||
public OmList(ObjectMapper objectMapper, Type type, int dbType, String pgType, DocPropertyType docType) {
|
||||
super(List.class, objectMapper, type, dbType, pgType, docType);
|
||||
public OmList(ObjectMapper objectMapper, AnnotatedField field, int dbType, String pgType, DocPropertyType docType) {
|
||||
super(List.class, objectMapper, field, dbType, pgType, docType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,8 +117,8 @@ public class ScalarTypeJsonObjectMapper {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static class OmMap extends Base<Map> {
|
||||
|
||||
public OmMap(ObjectMapper objectMapper, Type type, int dbType, String pgType) {
|
||||
super(Map.class, objectMapper, type, dbType, pgType, DocPropertyType.OBJECT);
|
||||
public OmMap(ObjectMapper objectMapper, AnnotatedField field, int dbType, String pgType) {
|
||||
super(Map.class, objectMapper, field, dbType, pgType, DocPropertyType.OBJECT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,9 +135,11 @@ public class ScalarTypeJsonObjectMapper {
|
||||
*/
|
||||
private static abstract class Base<T> extends ScalarTypeBase<T> {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
private final ObjectWriter objectWriter;
|
||||
|
||||
private final JavaType javaType;
|
||||
private final ObjectMapper objectReader;
|
||||
|
||||
private JavaType deserType;
|
||||
|
||||
private final String pgType;
|
||||
|
||||
@@ -140,12 +148,39 @@ public class ScalarTypeJsonObjectMapper {
|
||||
/**
|
||||
* Construct given the object mapper, property type and DB type for storage.
|
||||
*/
|
||||
public Base(Class<T> cls, ObjectMapper objectMapper, Type type, int dbType, String pgType, DocPropertyType docType) {
|
||||
public Base(Class<T> cls, ObjectMapper objectMapper, AnnotatedField field, int dbType, String pgType, DocPropertyType docType) {
|
||||
super(cls, false, dbType);
|
||||
this.pgType = pgType;
|
||||
this.docType = docType;
|
||||
this.objectMapper = objectMapper;
|
||||
this.javaType = objectMapper.getTypeFactory().constructType(type);
|
||||
this.objectReader = objectMapper;
|
||||
|
||||
JavaType javaType = field.getType();
|
||||
DeserializationConfig deserConfig = objectMapper.getDeserializationConfig();
|
||||
AnnotationIntrospector ai = deserConfig.getAnnotationIntrospector();
|
||||
|
||||
if (ai != null && javaType != null && !javaType.hasRawClass(Object.class)) {
|
||||
try {
|
||||
this.deserType = ai.refineDeserializationType(deserConfig, field, javaType);
|
||||
} catch (JsonMappingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
this.deserType = javaType;
|
||||
}
|
||||
|
||||
SerializationConfig serConfig = objectMapper.getSerializationConfig();
|
||||
ai = deserConfig.getAnnotationIntrospector();
|
||||
|
||||
if (ai != null && javaType != null && !javaType.hasRawClass(Object.class)) {
|
||||
try {
|
||||
JavaType serType = ai.refineSerializationType(serConfig, field, javaType);
|
||||
this.objectWriter = objectMapper.writerFor(serType);
|
||||
} catch (JsonMappingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
this.objectWriter = objectMapper.writerFor(javaType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,7 +206,7 @@ public class ScalarTypeJsonObjectMapper {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.readValue(json, javaType);
|
||||
return objectReader.readValue(json, deserType);
|
||||
} catch (IOException e) {
|
||||
throw new SQLException("Unable to convert JSON", e);
|
||||
}
|
||||
@@ -187,7 +222,7 @@ public class ScalarTypeJsonObjectMapper {
|
||||
bind.setNull(Types.VARCHAR); // use varchar, otherwise SqlServer/db2 will fail with 'Invalid JDBC data type 5.001.'
|
||||
} else {
|
||||
try {
|
||||
String json = objectMapper.writeValueAsString(value);
|
||||
String json = objectWriter.writeValueAsString(value);
|
||||
bind.setString(json);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new SQLException("Unable to create JSON", e);
|
||||
@@ -212,7 +247,7 @@ public class ScalarTypeJsonObjectMapper {
|
||||
@Override
|
||||
public String formatValue(T value) {
|
||||
try {
|
||||
return objectMapper.writeValueAsString(value);
|
||||
return objectWriter.writeValueAsString(value);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new PersistenceException("Unable to create JSON", e);
|
||||
}
|
||||
@@ -221,7 +256,7 @@ public class ScalarTypeJsonObjectMapper {
|
||||
@Override
|
||||
public T parse(String value) {
|
||||
try {
|
||||
return objectMapper.readValue(value, javaType);
|
||||
return objectReader.readValue(value, deserType);
|
||||
} catch (IOException e) {
|
||||
throw new PersistenceException("Unable to convert JSON", e);
|
||||
}
|
||||
@@ -244,12 +279,12 @@ public class ScalarTypeJsonObjectMapper {
|
||||
|
||||
@Override
|
||||
public T jsonRead(JsonParser parser) throws IOException {
|
||||
return objectMapper.readValue(parser, javaType);
|
||||
return objectReader.readValue(parser, deserType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator writer, T value) throws IOException {
|
||||
objectMapper.writeValue(writer, value);
|
||||
objectWriter.writeValue(writer, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.annotation.DbArray;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
|
||||
import javax.persistence.EnumType;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -57,7 +58,7 @@ public interface TypeManager {
|
||||
* Note that type expected to be JsonNode or Map.
|
||||
* </p>
|
||||
*/
|
||||
ScalarType<?> getJsonScalarType(Class<?> type, int dbType, int dbLength, Type genericType);
|
||||
ScalarType<?> getJsonScalarType(DeployBeanProperty prop, int dbType, int dbLength);
|
||||
|
||||
/**
|
||||
* Return the ScalarType used to handle DB ARRAY.
|
||||
|
||||
@@ -54,7 +54,7 @@ public class TestTransient extends BaseTestCase {
|
||||
selected = c.getSelected();
|
||||
Assert.assertNotNull(selected);
|
||||
|
||||
String updateStmt = "update customer set name = 'Rob' where id = :id";
|
||||
String updateStmt = "update customer set name = 'testTrans2' where id = :id";
|
||||
int rows = Ebean.createUpdate(Customer.class, updateStmt).set("id", custId).execute();
|
||||
|
||||
Assert.assertTrue("changed name back", 1 == rows);
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package org.tests.json;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.tests.model.json.EBasicJsonJackson;
|
||||
import org.tests.model.json.EBasicJsonJackson2;
|
||||
import org.tests.model.json.LongJacksonType;
|
||||
import org.tests.model.json.StringJacksonType;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
|
||||
public class TestDbJson_Jackson extends BaseTestCase {
|
||||
|
||||
|
||||
/**
|
||||
* This testcase verifies if the @JsonDeserialize Annotation will work properly in ebean.
|
||||
*/
|
||||
@Test
|
||||
public void testJsonDeserializeAnnotation() throws IOException {
|
||||
|
||||
EBasicJsonJackson bean = new EBasicJsonJackson();
|
||||
|
||||
bean.setName("stuff");
|
||||
|
||||
bean.setPlainValue("plain");
|
||||
|
||||
bean.getValueSet().add("A");
|
||||
bean.getValueSet().add("B");
|
||||
|
||||
bean.getValueList().add("A");
|
||||
bean.getValueList().add("B");
|
||||
|
||||
bean.getValueMap().put(1, "one");
|
||||
bean.getValueMap().put(2, "two");
|
||||
|
||||
ObjectMapper mapper = (ObjectMapper) Ebean.getDefaultServer().getPluginApi().getServerConfig().getObjectMapper();
|
||||
|
||||
String json = mapper.writeValueAsString(bean);
|
||||
EBasicJsonJackson found = mapper.readValue(json, EBasicJsonJackson.class);
|
||||
|
||||
// here we assert, that we can serialize/deserialize that bean with jackson
|
||||
assertThat(found.getPlainValue()).isEqualTo("plain");
|
||||
assertThat(found.getValueList()).containsExactly("A", "B");
|
||||
assertThat(found.getValueSet()).containsExactly("A", "B");
|
||||
assertThat(found.getValueMap()).containsEntry(1L, "one").containsEntry(2L, "two");
|
||||
|
||||
Ebean.save(bean);
|
||||
|
||||
// here we do the same and expect, that we can deserialize the bean also
|
||||
found = Ebean.find(EBasicJsonJackson.class, bean.getId());
|
||||
|
||||
assertThat(found.getPlainValue()).isEqualTo("plain");
|
||||
assertThat(found.getValueList()).containsExactly("A", "B");
|
||||
assertThat(found.getValueSet()).containsExactly("A", "B");
|
||||
assertThat(found.getValueMap()).containsEntry(1L, "one").containsEntry(2L, "two");
|
||||
}
|
||||
|
||||
/**
|
||||
* This testcase verifies if polymorph objects will work in ebean.
|
||||
*
|
||||
* for BasicJacksonType there exists two types and has a @JsonTypeInfo
|
||||
* annotation. It is expected that this information is also honored by ebean.
|
||||
*/
|
||||
@Test
|
||||
public void testPolymorph() throws IOException {
|
||||
|
||||
EBasicJsonJackson2 bean = new EBasicJsonJackson2();
|
||||
|
||||
bean.setName("stuff");
|
||||
|
||||
bean.setPlainValue(new LongJacksonType(42L));
|
||||
|
||||
bean.getValueSet().add(new StringJacksonType("A"));
|
||||
bean.getValueSet().add(new LongJacksonType(7l));
|
||||
|
||||
bean.getValueList().add(new StringJacksonType("A"));
|
||||
bean.getValueList().add(new LongJacksonType(7l));
|
||||
|
||||
bean.getValueMap().put(1, new StringJacksonType("A"));
|
||||
bean.getValueMap().put(2, new LongJacksonType(7l));
|
||||
|
||||
ObjectMapper mapper = (ObjectMapper) Ebean.getDefaultServer().getPluginApi().getServerConfig().getObjectMapper();
|
||||
|
||||
String json = mapper.writeValueAsString(bean);
|
||||
assertThat(json)
|
||||
.contains("\"type\":\"string\"")
|
||||
.contains("\"type\":\"long\"");
|
||||
EBasicJsonJackson2 found = mapper.readValue(json, EBasicJsonJackson2.class);
|
||||
|
||||
assertThat(found.getPlainValue()).isInstanceOf(LongJacksonType.class);
|
||||
assertThat(found.getValueList()).hasSize(2);
|
||||
assertThat(found.getValueSet()).hasSize(2);
|
||||
assertThat(found.getValueMap()).hasSize(2);;
|
||||
|
||||
Ebean.save(bean);
|
||||
|
||||
found = Ebean.find(EBasicJsonJackson2.class, bean.getId());
|
||||
|
||||
assertThat(found.getPlainValue()).isInstanceOf(LongJacksonType.class);
|
||||
assertThat(found.getValueList()).hasSize(2);
|
||||
assertThat(found.getValueSet()).hasSize(2);
|
||||
assertThat(found.getValueMap()).hasSize(2);;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.tests.json;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.tests.model.json.EBasicJsonJackson2;
|
||||
import org.tests.model.json.LongJacksonType;
|
||||
import org.tests.model.json.StringJacksonType;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
|
||||
public class TestDbJson_Jackson2 extends BaseTestCase {
|
||||
|
||||
private EBasicJsonJackson2 bean = new EBasicJsonJackson2();
|
||||
|
||||
private EBasicJsonJackson2 found;
|
||||
|
||||
@Test
|
||||
public void insert() throws IOException {
|
||||
|
||||
bean.setName("stuff");
|
||||
|
||||
bean.setPlainValue(new LongJacksonType(42L));
|
||||
|
||||
bean.getValueSet().add(new StringJacksonType("A"));
|
||||
bean.getValueSet().add(new LongJacksonType(7l));
|
||||
|
||||
bean.getValueList().add(new StringJacksonType("A"));
|
||||
bean.getValueList().add(new LongJacksonType(7l));
|
||||
|
||||
bean.getValueMap().put(1, new StringJacksonType("A"));
|
||||
bean.getValueMap().put(2, new LongJacksonType(7l));
|
||||
|
||||
ObjectMapper mapper = (ObjectMapper) Ebean.getDefaultServer().getPluginApi().getServerConfig().getObjectMapper();
|
||||
|
||||
String json = mapper.writeValueAsString(bean);
|
||||
found = mapper.readValue(json, EBasicJsonJackson2.class);
|
||||
|
||||
assertThat(found.getPlainValue()).isInstanceOf(LongJacksonType.class);
|
||||
assertThat(found.getValueList()).hasSize(2);
|
||||
assertThat(found.getValueSet()).hasSize(2);
|
||||
assertThat(found.getValueMap()).hasSize(2);;
|
||||
|
||||
Ebean.save(bean);
|
||||
|
||||
found = Ebean.find(EBasicJsonJackson2.class, bean.getId());
|
||||
|
||||
assertThat(found.getPlainValue()).isInstanceOf(LongJacksonType.class);
|
||||
assertThat(found.getValueList()).hasSize(2);
|
||||
assertThat(found.getValueSet()).hasSize(2);
|
||||
assertThat(found.getValueMap()).hasSize(2);;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.tests.model.json;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
|
||||
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = LongJacksonType.class, name = "long"),
|
||||
@JsonSubTypes.Type(value = StringJacksonType.class, name = "string")
|
||||
})
|
||||
public interface BasicJacksonType<T> {
|
||||
T getValue();
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.tests.model.json;
|
||||
|
||||
import io.ebean.annotation.DbJson;
|
||||
import io.ebean.annotation.DbJsonB;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
public class EBasicJsonJackson {
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
String name;
|
||||
|
||||
@DbJson(length = 700)
|
||||
@JsonDeserialize(contentAs = String.class)
|
||||
Set<Object> valueSet = new LinkedHashSet<>();
|
||||
|
||||
@DbJsonB
|
||||
@JsonDeserialize(contentAs = String.class)
|
||||
List<Object> valueList = new ArrayList<>();
|
||||
|
||||
@DbJson(length = 700)
|
||||
@JsonDeserialize(keyAs = Long.class, contentAs = String.class)
|
||||
Map<Object, Object> valueMap = new LinkedHashMap<>();
|
||||
|
||||
@DbJson(length = 500)
|
||||
@JsonDeserialize(as = String.class)
|
||||
Object plainValue;
|
||||
|
||||
@Version
|
||||
Long version;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Set<Object> getValueSet() {
|
||||
return valueSet;
|
||||
}
|
||||
|
||||
public void setValueSet(Set<Object> valueSet) {
|
||||
this.valueSet = valueSet;
|
||||
}
|
||||
|
||||
public List<Object> getValueList() {
|
||||
return valueList;
|
||||
}
|
||||
|
||||
public void setValueList(List<Object> valueList) {
|
||||
this.valueList = valueList;
|
||||
}
|
||||
|
||||
public Object getPlainValue() {
|
||||
return plainValue;
|
||||
}
|
||||
|
||||
public void setPlainValue(Object plainValue) {
|
||||
this.plainValue = plainValue;
|
||||
}
|
||||
|
||||
public Map<Object, Object> getValueMap() {
|
||||
return valueMap;
|
||||
}
|
||||
|
||||
public void setValueMap(Map<Object, Object> valueMap) {
|
||||
this.valueMap = valueMap;
|
||||
}
|
||||
|
||||
public Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package org.tests.model.json;
|
||||
|
||||
import io.ebean.annotation.DbJson;
|
||||
import io.ebean.annotation.DbJsonB;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
public class EBasicJsonJackson2 {
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
String name;
|
||||
|
||||
@DbJson(length = 700)
|
||||
Set<BasicJacksonType<?>> valueSet = new LinkedHashSet<>();
|
||||
|
||||
@DbJsonB
|
||||
List<BasicJacksonType<?>> valueList = new ArrayList<>();
|
||||
|
||||
@DbJson(length = 700)
|
||||
@JsonDeserialize(keyAs = Long.class)
|
||||
Map<Number, BasicJacksonType<?>> valueMap = new LinkedHashMap<>();
|
||||
|
||||
@DbJson(length = 500)
|
||||
BasicJacksonType<?> plainValue;
|
||||
|
||||
@Version
|
||||
Long version;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Set<BasicJacksonType<?>> getValueSet() {
|
||||
return valueSet;
|
||||
}
|
||||
|
||||
public void setValueSet(Set<BasicJacksonType<?>> valueSet) {
|
||||
this.valueSet = valueSet;
|
||||
}
|
||||
|
||||
public List<BasicJacksonType<?>> getValueList() {
|
||||
return valueList;
|
||||
}
|
||||
|
||||
public void setValueList(List<BasicJacksonType<?>> valueList) {
|
||||
this.valueList = valueList;
|
||||
}
|
||||
|
||||
public BasicJacksonType<?> getPlainValue() {
|
||||
return plainValue;
|
||||
}
|
||||
|
||||
public void setPlainValue(BasicJacksonType<?> plainValue) {
|
||||
this.plainValue = plainValue;
|
||||
}
|
||||
|
||||
public Map<Number, BasicJacksonType<?>> getValueMap() {
|
||||
return valueMap;
|
||||
}
|
||||
|
||||
public void setValueMap(Map<Number, BasicJacksonType<?>> valueMap) {
|
||||
this.valueMap = valueMap;
|
||||
}
|
||||
|
||||
public Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.tests.model.json;
|
||||
|
||||
public class LongJacksonType implements BasicJacksonType<Long> {
|
||||
|
||||
private Long value;
|
||||
|
||||
public LongJacksonType() {}
|
||||
|
||||
public LongJacksonType(Long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.tests.model.json;
|
||||
|
||||
public class StringJacksonType implements BasicJacksonType<String> {
|
||||
|
||||
private String value;
|
||||
|
||||
public StringJacksonType() {}
|
||||
|
||||
public StringJacksonType(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
10000,NEW,"Rob",01-JAN-2009,"12 someplace",Auckland,NZ
|
||||
10000,NEW,"Roland",01-JAN-2009,"12 someplace",Auckland,NZ
|
||||
,ACTIVE,"Greg",14-FEB-2009,"13 someplace",Sydney,AU
|
||||
,INACTIVE,"Dan",29-SEP-2009,"14 someplace",Auckland,NZ
|
||||
,NEW,"ARob",01-JAN-2009,"12 someplace",Auckland,NZ
|
||||
|
||||
|
Reference in New Issue
Block a user