mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#1223 - Support mapping @DbArray to a List or Set of enums
This commit is contained in:
@@ -18,7 +18,6 @@ import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import io.ebeaninternal.server.type.DataEncryptSupport;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
import io.ebeaninternal.server.type.ScalarTypeArray;
|
||||
import io.ebeaninternal.server.type.ScalarTypeEnumStandard;
|
||||
import io.ebeaninternal.server.type.SimpleAesEncryptor;
|
||||
import io.ebeaninternal.server.type.TypeManager;
|
||||
import org.slf4j.Logger;
|
||||
@@ -121,14 +120,8 @@ public class DeployUtil {
|
||||
if (scalarType == null) {
|
||||
// look for @DbEnumValue or @EnumValue annotations etc
|
||||
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) enumType;
|
||||
scalarType = typeManager.createEnumScalarType(enumClass);
|
||||
if (scalarType == null) {
|
||||
// use JPA normal Enum type (without mapping)
|
||||
EnumType type = enumerated != null ? enumerated.value() : null;
|
||||
scalarType = createEnumScalarTypePerSpec(enumType, type);
|
||||
}
|
||||
|
||||
typeManager.addEnumType(scalarType, enumClass);
|
||||
EnumType type = enumerated != null ? enumerated.value() : null;
|
||||
scalarType = typeManager.createEnumScalarType(enumClass, type);
|
||||
}
|
||||
prop.setScalarType(scalarType);
|
||||
prop.setDbType(scalarType.getJdbcType());
|
||||
@@ -145,20 +138,6 @@ public class DeployUtil {
|
||||
&& scalarType.getJdbcType() != Types.VARCHAR;
|
||||
}
|
||||
|
||||
private ScalarType<?> createEnumScalarTypePerSpec(Class<?> enumType, EnumType type) {
|
||||
|
||||
if (type == null) {
|
||||
// default as per spec is ORDINAL
|
||||
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
|
||||
|
||||
} else if (type == EnumType.ORDINAL) {
|
||||
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
|
||||
|
||||
} else {
|
||||
return new ScalarTypeEnumStandard.StringEnum(enumType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the ScalarType for this property.
|
||||
* <p>
|
||||
|
||||
@@ -12,6 +12,10 @@ interface ArrayElementConverter<T> {
|
||||
*/
|
||||
T toElement(Object rawValue);
|
||||
|
||||
default Object[] toDbArray(Object[] objects) {
|
||||
return objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* The UUID converter implementation.
|
||||
*/
|
||||
@@ -94,4 +98,30 @@ interface ArrayElementConverter<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String converter (noop based).
|
||||
*/
|
||||
class EnumConverter implements ArrayElementConverter {
|
||||
|
||||
private final ScalarType<?> scalarType;
|
||||
|
||||
EnumConverter(ScalarType<?> scalarType) {
|
||||
this.scalarType = scalarType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toElement(Object rawValue) {
|
||||
return scalarType.parse(rawValue.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toDbArray(Object[] objects) {
|
||||
Object[] dbArray = new Object[objects.length];
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
dbArray[i] = scalarType.format(objects[i]);
|
||||
}
|
||||
return dbArray;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.ebean.annotation.DbArray;
|
||||
import io.ebean.annotation.DbEnumType;
|
||||
import io.ebean.annotation.DbEnumValue;
|
||||
import io.ebean.annotation.EnumValue;
|
||||
import io.ebean.config.JsonConfig;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.JsonConfig;
|
||||
import io.ebean.config.ScalarTypeConverter;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.dbmigration.DbOffline;
|
||||
import io.ebeaninternal.api.ExtraTypeFactory;
|
||||
import io.ebeaninternal.dbmigration.DbOffline;
|
||||
import io.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.LocalDateTime;
|
||||
@@ -25,6 +25,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.EnumType;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -337,12 +338,18 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
Type valueType = getValueType(genericType);
|
||||
if (type.equals(List.class)) {
|
||||
if (arrayTypeListFactory != null) {
|
||||
if(isEnumType(valueType)) {
|
||||
return arrayTypeListFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), EnumType.STRING));
|
||||
}
|
||||
return arrayTypeListFactory.typeFor(valueType);
|
||||
}
|
||||
// fallback to JSON storage in VARCHAR column
|
||||
return new ScalarTypeJsonList.Varchar(getDocType(valueType));
|
||||
} else if (type.equals(Set.class)) {
|
||||
if (arrayTypeSetFactory != null) {
|
||||
if(isEnumType(valueType)) {
|
||||
return arrayTypeSetFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), EnumType.STRING));
|
||||
}
|
||||
return arrayTypeSetFactory.typeFor(valueType);
|
||||
}
|
||||
// fallback to JSON storage in VARCHAR column
|
||||
@@ -351,6 +358,15 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
throw new IllegalStateException("Type [" + type + "] not supported for @DbArray");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<? extends Enum<?>> asEnumClass(Type valueType) {
|
||||
return (Class<? extends Enum<?>>)valueType;
|
||||
}
|
||||
|
||||
private boolean isEnumType(Type valueType) {
|
||||
return valueType instanceof Class && ((Class<?>)valueType).isEnum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> getJsonScalarType(Class<?> type, int dbType, int dbLength, Type genericType) {
|
||||
|
||||
@@ -571,7 +587,36 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public ScalarType<?> createEnumScalarType(Class<? extends Enum<?>> enumType) {
|
||||
public ScalarType<?> createEnumScalarType(Class<? extends Enum<?>> enumType, EnumType type) {
|
||||
|
||||
ScalarType<?> scalarType = getScalarType(enumType);
|
||||
if (scalarType != null) {
|
||||
return scalarType;
|
||||
}
|
||||
|
||||
scalarType = createEnumScalarTypePerExtentions(enumType);
|
||||
if (scalarType == null) {
|
||||
// use JPA normal Enum type (without mapping)
|
||||
scalarType = createEnumScalarTypePerSpec(enumType, type);
|
||||
}
|
||||
addEnumType(scalarType, enumType);
|
||||
return scalarType;
|
||||
}
|
||||
|
||||
private ScalarType<?> createEnumScalarTypePerSpec(Class<?> enumType, EnumType type) {
|
||||
if (type == null) {
|
||||
// default as per spec is ORDINAL
|
||||
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
|
||||
|
||||
} else if (type == EnumType.ORDINAL) {
|
||||
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
|
||||
|
||||
} else {
|
||||
return new ScalarTypeEnumStandard.StringEnum(enumType);
|
||||
}
|
||||
}
|
||||
|
||||
private ScalarType<?> createEnumScalarTypePerExtentions(Class<? extends Enum<?>> enumType) {
|
||||
|
||||
Method[] methods = enumType.getMethods();
|
||||
for (Method method : methods) {
|
||||
|
||||
@@ -12,4 +12,8 @@ public interface PlatformArrayTypeFactory {
|
||||
*/
|
||||
ScalarType<?> typeFor(Type valueType);
|
||||
|
||||
/**
|
||||
* Return the ScalarType to handle DB ARRAY for the given enum element type.
|
||||
*/
|
||||
ScalarType<?> typeForEnum(ScalarType<?> scalarType);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import io.ebean.text.json.EJson;
|
||||
import io.ebeaninternal.json.ModifyAwareList;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.IOException;
|
||||
@@ -57,6 +57,12 @@ public class ScalarTypeArrayList extends ScalarTypeJsonCollection<List> implemen
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public ScalarTypeArrayList typeForEnum(ScalarType<?> scalarType) {
|
||||
return new ScalarTypeArrayList("varchar", DocPropertyType.TEXT, new ArrayElementConverter.EnumConverter(scalarType));
|
||||
}
|
||||
}
|
||||
|
||||
private final String arrayType;
|
||||
@@ -92,7 +98,7 @@ public class ScalarTypeArrayList extends ScalarTypeJsonCollection<List> implemen
|
||||
}
|
||||
|
||||
protected Object[] toArray(List value) {
|
||||
return value.toArray();
|
||||
return converter.toDbArray(value.toArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -46,6 +46,11 @@ class ScalarTypeArrayListH2 extends ScalarTypeArrayList {
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> typeForEnum(ScalarType<?> scalarType) {
|
||||
return new ScalarTypeArrayListH2("varchar", DocPropertyType.TEXT, new ArrayElementConverter.EnumConverter(scalarType));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
||||
@@ -56,6 +56,12 @@ public class ScalarTypeArraySet<T> extends ScalarTypeJsonCollection<Set<T>> impl
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping on set");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public ScalarTypeArraySet typeForEnum(ScalarType<?> scalarType) {
|
||||
return new ScalarTypeArraySet("varchar", DocPropertyType.TEXT, new ArrayElementConverter.EnumConverter(scalarType));
|
||||
}
|
||||
}
|
||||
|
||||
private final String arrayType;
|
||||
@@ -91,7 +97,7 @@ public class ScalarTypeArraySet<T> extends ScalarTypeJsonCollection<Set<T>> impl
|
||||
}
|
||||
|
||||
protected Object[] toArray(Set<T> value) {
|
||||
return value.toArray();
|
||||
return converter.toDbArray(value.toArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,6 +28,7 @@ class ScalarTypeArraySetH2<T> extends ScalarTypeArraySet<T> {
|
||||
* Return the ScalarType to use based on the List's generic parameter type.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ScalarTypeArraySetH2<?> typeFor(Type valueType) {
|
||||
if (valueType.equals(java.util.UUID.class)) {
|
||||
return UUID;
|
||||
@@ -46,9 +47,15 @@ class ScalarTypeArraySetH2<T> extends ScalarTypeArraySet<T> {
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarTypeArraySetH2 typeForEnum(ScalarType<?> scalarType) {
|
||||
return new ScalarTypeArraySetH2("varchar", DocPropertyType.TEXT, new ArrayElementConverter.EnumConverter(scalarType));
|
||||
}
|
||||
}
|
||||
|
||||
private ScalarTypeArraySetH2(String arrayType, DocPropertyType docPropertyType, ArrayElementConverter<T> converter) {
|
||||
@SuppressWarnings("unchecked")
|
||||
private ScalarTypeArraySetH2(String arrayType, DocPropertyType docPropertyType, ArrayElementConverter converter) {
|
||||
super(arrayType, docPropertyType, converter);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.annotation.DbArray;
|
||||
|
||||
import javax.persistence.EnumType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
@@ -43,7 +44,7 @@ public interface TypeManager {
|
||||
* Create a ScalarType for an Enum using a mapping (rather than JPA Ordinal
|
||||
* or String which has limitations).
|
||||
*/
|
||||
ScalarType<?> createEnumScalarType(Class<? extends Enum<?>> enumType);
|
||||
ScalarType<?> createEnumScalarType(Class<? extends Enum<?>> enumType, EnumType enumerated);
|
||||
|
||||
/**
|
||||
* Return the ScalarType used to handle JSON content.
|
||||
|
||||
Reference in New Issue
Block a user