mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-25 23:59:38 +00:00
#1893 - @DbArray with @NotNull ... should persist empty db array rather than fail NOT NULL constraint
This commit is contained in:
@@ -221,6 +221,38 @@ public class AnnotationFields extends AnnotationParser {
|
||||
util.setLobType(prop);
|
||||
}
|
||||
|
||||
Length length = get(prop, Length.class);
|
||||
if (length != null) {
|
||||
prop.setDbLength(length.value());
|
||||
}
|
||||
|
||||
io.ebean.annotation.NotNull nonNull = get(prop, io.ebean.annotation.NotNull.class);
|
||||
if (nonNull != null) {
|
||||
prop.setNullable(false);
|
||||
}
|
||||
|
||||
if (validationAnnotations) {
|
||||
NotNull notNull = get(prop, NotNull.class);
|
||||
if (notNull != null && isEbeanValidationGroups(notNull.groups())) {
|
||||
// Not null on all validation groups so enable
|
||||
// DDL generation of Not Null Constraint
|
||||
prop.setNullable(false);
|
||||
}
|
||||
|
||||
if (!prop.isLob()) {
|
||||
// take the max size of all @Size annotations
|
||||
int maxSize = -1;
|
||||
for (Size size : getAll(prop, Size.class)) {
|
||||
if (size.max() < Integer.MAX_VALUE) {
|
||||
maxSize = Math.max(maxSize, size.max());
|
||||
}
|
||||
}
|
||||
if (maxSize != -1) {
|
||||
prop.setDbLength(maxSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (get(prop, TenantId.class) != null) {
|
||||
prop.setTenantId();
|
||||
}
|
||||
@@ -322,41 +354,8 @@ public class AnnotationFields extends AnnotationParser {
|
||||
prop.setExcludedFromHistory();
|
||||
}
|
||||
|
||||
Length length = get(prop, Length.class);
|
||||
if (length != null) {
|
||||
prop.setDbLength(length.value());
|
||||
}
|
||||
|
||||
io.ebean.annotation.NotNull nonNull = get(prop, io.ebean.annotation.NotNull.class);
|
||||
if (nonNull != null) {
|
||||
prop.setNullable(false);
|
||||
}
|
||||
|
||||
readDbMigration(prop);
|
||||
|
||||
|
||||
if (validationAnnotations) {
|
||||
NotNull notNull = get(prop, NotNull.class);
|
||||
if (notNull != null && isEbeanValidationGroups(notNull.groups())) {
|
||||
// Not null on all validation groups so enable
|
||||
// DDL generation of Not Null Constraint
|
||||
prop.setNullable(false);
|
||||
}
|
||||
|
||||
if (!prop.isLob()) {
|
||||
// take the max size of all @Size annotations
|
||||
int maxSize = -1;
|
||||
for (Size size : getAll(prop, Size.class)) {
|
||||
if (size.max() < Integer.MAX_VALUE) {
|
||||
maxSize = Math.max(maxSize, size.max());
|
||||
}
|
||||
}
|
||||
if (maxSize != -1) {
|
||||
prop.setDbLength(maxSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Want to process last so we can use with @Formula
|
||||
Transient t = get(prop, Transient.class);
|
||||
if (t != null) {
|
||||
|
||||
@@ -191,7 +191,7 @@ public class DeployUtil {
|
||||
void setDbArray(DeployBeanProperty prop, DbArray dbArray) {
|
||||
|
||||
Class<?> type = prop.getPropertyType();
|
||||
ScalarType<?> scalarType = typeManager.getArrayScalarType(type, dbArray, prop.getGenericType());
|
||||
ScalarType<?> scalarType = typeManager.getArrayScalarType(type, dbArray, prop.getGenericType(), prop.isNullable());
|
||||
if (scalarType == null) {
|
||||
throw new RuntimeException("No ScalarType for @DbArray type for [" + prop.getFullBeanName() + "]");
|
||||
}
|
||||
|
||||
@@ -354,29 +354,42 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> getArrayScalarType(Class<?> type, DbArray dbArray, Type genericType) {
|
||||
public ScalarType<?> getArrayScalarType(Class<?> type, DbArray dbArray, Type genericType, boolean nullable) {
|
||||
|
||||
Type valueType = getValueType(genericType);
|
||||
if (type.equals(List.class)) {
|
||||
if (arrayTypeListFactory != null) {
|
||||
if (isEnumType(valueType)) {
|
||||
return arrayTypeListFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), null));
|
||||
}
|
||||
return arrayTypeListFactory.typeFor(valueType);
|
||||
}
|
||||
// fallback to JSON storage in VARCHAR column
|
||||
return new ScalarTypeJsonList.Varchar(getDocType(valueType));
|
||||
return getArrayScalarTypeList(valueType, nullable);
|
||||
|
||||
} else if (type.equals(Set.class)) {
|
||||
if (arrayTypeSetFactory != null) {
|
||||
if (isEnumType(valueType)) {
|
||||
return arrayTypeSetFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), null));
|
||||
}
|
||||
return arrayTypeSetFactory.typeFor(valueType);
|
||||
}
|
||||
// fallback to JSON storage in VARCHAR column
|
||||
return new ScalarTypeJsonSet.Varchar(getDocType(valueType));
|
||||
return getArrayScalarTypeSet(valueType, nullable);
|
||||
|
||||
} else {
|
||||
throw new IllegalStateException("Type [" + type + "] not supported for @DbArray");
|
||||
}
|
||||
throw new IllegalStateException("Type [" + type + "] not supported for @DbArray");
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private ScalarType<?> getArrayScalarTypeSet(Type valueType, boolean nullable) {
|
||||
if (arrayTypeSetFactory != null) {
|
||||
if (isEnumType(valueType)) {
|
||||
return arrayTypeSetFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), null), nullable);
|
||||
}
|
||||
return arrayTypeSetFactory.typeFor(valueType, nullable);
|
||||
}
|
||||
// fallback to JSON storage in VARCHAR column
|
||||
return new ScalarTypeJsonSet.Varchar(getDocType(valueType), nullable);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private ScalarType<?> getArrayScalarTypeList(Type valueType, boolean nullable) {
|
||||
if (arrayTypeListFactory != null) {
|
||||
if (isEnumType(valueType)) {
|
||||
return arrayTypeListFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), null), nullable);
|
||||
}
|
||||
return arrayTypeListFactory.typeFor(valueType, nullable);
|
||||
}
|
||||
// fallback to JSON storage in VARCHAR column
|
||||
return new ScalarTypeJsonList.Varchar(getDocType(valueType), nullable);
|
||||
}
|
||||
|
||||
private Class<? extends Enum<?>> asEnumClass(Type valueType) {
|
||||
@@ -398,7 +411,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
if (type.equals(List.class)) {
|
||||
DocPropertyType docType = getDocType(genericType);
|
||||
if (!hasJacksonAnnotations && isValueTypeSimple(genericType)) {
|
||||
return ScalarTypeJsonList.typeFor(postgres, dbType, docType);
|
||||
return ScalarTypeJsonList.typeFor(postgres, dbType, docType, prop.isNullable());
|
||||
} else {
|
||||
return createJsonObjectMapperType(prop, dbType, docType);
|
||||
}
|
||||
@@ -407,7 +420,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
if (type.equals(Set.class)) {
|
||||
DocPropertyType docType = getDocType(genericType);
|
||||
if (!hasJacksonAnnotations && isValueTypeSimple(genericType)) {
|
||||
return ScalarTypeJsonSet.typeFor(postgres, dbType, docType);
|
||||
return ScalarTypeJsonSet.typeFor(postgres, dbType, docType, prop.isNullable());
|
||||
} else {
|
||||
return createJsonObjectMapperType(prop, dbType, docType);
|
||||
}
|
||||
@@ -432,8 +445,6 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
return jsonNodeClob;
|
||||
case DbPlatformType.JSONB:
|
||||
return jsonNodeJsonb;
|
||||
case DbPlatformType.JSON:
|
||||
return jsonNodeJson;
|
||||
default:
|
||||
return jsonNodeJson;
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ public interface PlatformArrayTypeFactory {
|
||||
/**
|
||||
* Return the ScalarType to handle DB ARRAY for the given element type.
|
||||
*/
|
||||
ScalarType<?> typeFor(Type valueType);
|
||||
ScalarType<?> typeFor(Type valueType, boolean nullable);
|
||||
|
||||
/**
|
||||
* Return the ScalarType to handle DB ARRAY for the given enum element type.
|
||||
*/
|
||||
ScalarType<?> typeForEnum(ScalarType<?> scalarType);
|
||||
ScalarType<?> typeForEnum(ScalarType<?> scalarType, boolean nullable);
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@ import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
|
||||
import java.sql.Array;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
abstract class ScalarTypeArrayBase<T> extends ScalarTypeJsonCollection<T> {
|
||||
|
||||
ScalarTypeArrayBase(Class<T> type, int dbType, DocPropertyType docPropertyType) {
|
||||
super(type, dbType, docPropertyType);
|
||||
ScalarTypeArrayBase(Class<T> type, int dbType, DocPropertyType docPropertyType, boolean nullable) {
|
||||
super(type, dbType, docPropertyType, nullable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,4 +68,14 @@ abstract class ScalarTypeArrayBase<T> extends ScalarTypeJsonCollection<T> {
|
||||
|
||||
protected abstract T fromArray(Object[] array1);
|
||||
|
||||
static String arrayTypeFor(ScalarType<?> scalarType) {
|
||||
switch (scalarType.getJdbcType()) {
|
||||
case Types.INTEGER:
|
||||
return "integer";
|
||||
case Types.VARCHAR:
|
||||
return "varchar";
|
||||
default:
|
||||
throw new IllegalArgumentException("JdbcType [" + scalarType.getJdbcType() + "] not supported for @DbArray mapping on set.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,65 +14,56 @@ import java.lang.reflect.Type;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.util.Collections.EMPTY_LIST;
|
||||
|
||||
/**
|
||||
* Type mapped for DB ARRAY type (Postgres only effectively).
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class ScalarTypeArrayList extends ScalarTypeArrayBase<List> implements ScalarTypeArray {
|
||||
|
||||
private static ScalarTypeArrayList UUID = new ScalarTypeArrayList("uuid", DocPropertyType.UUID, ArrayElementConverter.UUID);
|
||||
private static ScalarTypeArrayList LONG = new ScalarTypeArrayList("bigint", DocPropertyType.LONG, ArrayElementConverter.LONG);
|
||||
private static ScalarTypeArrayList INTEGER = new ScalarTypeArrayList("integer", DocPropertyType.INTEGER, ArrayElementConverter.INTEGER);
|
||||
private static ScalarTypeArrayList DOUBLE = new ScalarTypeArrayList("float", DocPropertyType.DOUBLE, ArrayElementConverter.DOUBLE);
|
||||
private static ScalarTypeArrayList STRING = new ScalarTypeArrayList("varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING);
|
||||
|
||||
static PlatformArrayTypeFactory factory() {
|
||||
return new Factory();
|
||||
}
|
||||
|
||||
static class Factory implements PlatformArrayTypeFactory {
|
||||
|
||||
private final Map<String, ScalarTypeArrayList> cache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Return the ScalarType to use based on the List's generic parameter type.
|
||||
*/
|
||||
@Override
|
||||
public ScalarTypeArrayList typeFor(Type valueType) {
|
||||
if (valueType.equals(UUID.class)) {
|
||||
return UUID;
|
||||
public ScalarTypeArrayList typeFor(Type valueType, boolean nullable) {
|
||||
synchronized (this) {
|
||||
String key = valueType + ":" + nullable;
|
||||
if (valueType.equals(UUID.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "uuid", DocPropertyType.UUID, ArrayElementConverter.UUID));
|
||||
}
|
||||
if (valueType.equals(Long.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "bigint", DocPropertyType.LONG, ArrayElementConverter.LONG));
|
||||
}
|
||||
if (valueType.equals(Integer.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "integer", DocPropertyType.INTEGER, ArrayElementConverter.INTEGER));
|
||||
}
|
||||
if (valueType.equals(Double.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "float", DocPropertyType.DOUBLE, ArrayElementConverter.DOUBLE));
|
||||
}
|
||||
if (valueType.equals(String.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING));
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
}
|
||||
if (valueType.equals(Long.class)) {
|
||||
return LONG;
|
||||
}
|
||||
if (valueType.equals(Integer.class)) {
|
||||
return INTEGER;
|
||||
}
|
||||
if (valueType.equals(Double.class)) {
|
||||
return DOUBLE;
|
||||
}
|
||||
if (valueType.equals(String.class)) {
|
||||
return STRING;
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarTypeArrayList typeForEnum(ScalarType<?> scalarType) {
|
||||
final String arrayType;
|
||||
switch (scalarType.getJdbcType()) {
|
||||
case Types.INTEGER:
|
||||
arrayType = "integer";
|
||||
break;
|
||||
case Types.VARCHAR:
|
||||
arrayType = "varchar";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("JdbcType [" + scalarType.getJdbcType() + "] not supported for @DbArray mapping on set.");
|
||||
}
|
||||
|
||||
return new ScalarTypeArrayList(arrayType, scalarType.getDocType(), new ArrayElementConverter.EnumConverter(scalarType));
|
||||
public ScalarTypeArrayList typeForEnum(ScalarType<?> scalarType, boolean nullable) {
|
||||
return new ScalarTypeArrayList(nullable, arrayTypeFor(scalarType), scalarType.getDocType(), new ArrayElementConverter.EnumConverter(scalarType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,8 +71,8 @@ public class ScalarTypeArrayList extends ScalarTypeArrayBase<List> implements Sc
|
||||
|
||||
private final ArrayElementConverter converter;
|
||||
|
||||
public ScalarTypeArrayList(String arrayType, DocPropertyType docPropertyType, ArrayElementConverter converter) {
|
||||
super(List.class, Types.ARRAY, docPropertyType);
|
||||
public ScalarTypeArrayList(boolean nullable, String arrayType, DocPropertyType docPropertyType, ArrayElementConverter converter) {
|
||||
super(List.class, Types.ARRAY, docPropertyType, nullable);
|
||||
this.arrayType = arrayType;
|
||||
this.converter = converter;
|
||||
}
|
||||
@@ -120,12 +111,21 @@ public class ScalarTypeArrayList extends ScalarTypeArrayBase<List> implements Sc
|
||||
@Override
|
||||
public void bind(DataBind bind, List value) throws SQLException {
|
||||
if (value == null) {
|
||||
bind.setNull(Types.ARRAY);
|
||||
bindNull(bind);
|
||||
} else {
|
||||
bind.setArray(arrayType, toArray(value));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindNull(DataBind bind) throws SQLException {
|
||||
if (nullable) {
|
||||
bind.setNull(Types.ARRAY);
|
||||
} else {
|
||||
bind.setArray(arrayType, toArray(EMPTY_LIST));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(List value) {
|
||||
try {
|
||||
|
||||
@@ -5,66 +5,78 @@ import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.util.Collections.EMPTY_LIST;
|
||||
|
||||
/**
|
||||
* H2 database support for DB ARRAY.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
class ScalarTypeArrayListH2 extends ScalarTypeArrayList {
|
||||
|
||||
private static ScalarTypeArrayListH2 UUID = new ScalarTypeArrayListH2("uuid", DocPropertyType.UUID, ArrayElementConverter.UUID);
|
||||
private static ScalarTypeArrayListH2 LONG = new ScalarTypeArrayListH2("bigint", DocPropertyType.LONG, ArrayElementConverter.LONG);
|
||||
private static ScalarTypeArrayListH2 INTEGER = new ScalarTypeArrayListH2("integer", DocPropertyType.INTEGER, ArrayElementConverter.INTEGER);
|
||||
private static ScalarTypeArrayListH2 DOUBLE = new ScalarTypeArrayListH2("double", DocPropertyType.DOUBLE, ArrayElementConverter.DOUBLE);
|
||||
private static ScalarTypeArrayListH2 STRING = new ScalarTypeArrayListH2("varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING);
|
||||
|
||||
static PlatformArrayTypeFactory factory() {
|
||||
return new ScalarTypeArrayListH2.Factory();
|
||||
}
|
||||
|
||||
static class Factory implements PlatformArrayTypeFactory {
|
||||
|
||||
private final Map<String, ScalarTypeArrayListH2> cache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Return the ScalarType to use based on the List's generic parameter type.
|
||||
*/
|
||||
@Override
|
||||
public ScalarTypeArrayListH2 typeFor(Type valueType) {
|
||||
if (valueType.equals(java.util.UUID.class)) {
|
||||
return UUID;
|
||||
public ScalarType<?> typeFor(Type valueType, boolean nullable) {
|
||||
synchronized (this) {
|
||||
String key = valueType + ":" + nullable;
|
||||
if (valueType.equals(UUID.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayListH2(nullable, "uuid", DocPropertyType.UUID, ArrayElementConverter.UUID));
|
||||
}
|
||||
if (valueType.equals(Long.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayListH2(nullable, "bigint", DocPropertyType.LONG, ArrayElementConverter.LONG));
|
||||
}
|
||||
if (valueType.equals(Integer.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayListH2(nullable, "integer", DocPropertyType.INTEGER, ArrayElementConverter.INTEGER));
|
||||
}
|
||||
if (valueType.equals(Double.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayListH2(nullable, "float", DocPropertyType.DOUBLE, ArrayElementConverter.DOUBLE));
|
||||
}
|
||||
if (valueType.equals(String.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayListH2(nullable, "varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING));
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
}
|
||||
if (valueType.equals(Long.class)) {
|
||||
return LONG;
|
||||
}
|
||||
if (valueType.equals(Integer.class)) {
|
||||
return INTEGER;
|
||||
}
|
||||
if (valueType.equals(Double.class)) {
|
||||
return DOUBLE;
|
||||
}
|
||||
if (valueType.equals(String.class)) {
|
||||
return STRING;
|
||||
}
|
||||
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));
|
||||
public ScalarType<?> typeForEnum(ScalarType<?> scalarType, boolean nullable) {
|
||||
return new ScalarTypeArrayListH2(nullable, "varchar", DocPropertyType.TEXT, new ArrayElementConverter.EnumConverter(scalarType));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private ScalarTypeArrayListH2(String arrayType, DocPropertyType docPropertyType, ArrayElementConverter converter) {
|
||||
super(arrayType, docPropertyType, converter);
|
||||
private ScalarTypeArrayListH2(boolean nullable, String arrayType, DocPropertyType docPropertyType, ArrayElementConverter converter) {
|
||||
super(nullable, arrayType, docPropertyType, converter);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void bind(DataBind bind, List value) throws SQLException {
|
||||
if (value == null) {
|
||||
bind.setNull(Types.ARRAY);
|
||||
bindNull(bind);
|
||||
} else {
|
||||
bind.setObject(toArray(value));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindNull(DataBind bind) throws SQLException {
|
||||
if (nullable) {
|
||||
bind.setNull(Types.ARRAY);
|
||||
} else {
|
||||
bind.setObject(toArray(EMPTY_LIST));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,20 +13,19 @@ import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.util.Collections.EMPTY_SET;
|
||||
|
||||
/**
|
||||
* Type mapped for DB ARRAY type (Postgres only effectively).
|
||||
*/
|
||||
public class ScalarTypeArraySet<T> extends ScalarTypeArrayBase<Set<T>> implements ScalarTypeArray {
|
||||
|
||||
private static final ScalarTypeArraySet<UUID> UUID = new ScalarTypeArraySet<>("uuid", DocPropertyType.UUID, ArrayElementConverter.UUID);
|
||||
private static final ScalarTypeArraySet<Long> LONG = new ScalarTypeArraySet<>("bigint", DocPropertyType.LONG, ArrayElementConverter.LONG);
|
||||
private static final ScalarTypeArraySet<Integer> INTEGER = new ScalarTypeArraySet<>("integer", DocPropertyType.INTEGER, ArrayElementConverter.INTEGER);
|
||||
private static final ScalarTypeArraySet<Double> DOUBLE = new ScalarTypeArraySet<>("float", DocPropertyType.DOUBLE, ArrayElementConverter.DOUBLE);
|
||||
private static final ScalarTypeArraySet<String> STRING = new ScalarTypeArraySet<>("varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING);
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public class ScalarTypeArraySet extends ScalarTypeArrayBase<Set> implements ScalarTypeArray {
|
||||
|
||||
static PlatformArrayTypeFactory factory() {
|
||||
return new Factory();
|
||||
@@ -34,54 +33,46 @@ public class ScalarTypeArraySet<T> extends ScalarTypeArrayBase<Set<T>> implement
|
||||
|
||||
static class Factory implements PlatformArrayTypeFactory {
|
||||
|
||||
private final Map<String, ScalarTypeArraySet> cache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Return the ScalarType to use based on the List's generic parameter type.
|
||||
*/
|
||||
@Override
|
||||
public ScalarTypeArraySet<?> typeFor(Type valueType) {
|
||||
if (valueType.equals(UUID.class)) {
|
||||
return UUID;
|
||||
public ScalarType<?> typeFor(Type valueType, boolean nullable) {
|
||||
synchronized (this) {
|
||||
String key = valueType + ":" + nullable;
|
||||
if (valueType.equals(UUID.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySet(nullable, "uuid", DocPropertyType.UUID, ArrayElementConverter.UUID));
|
||||
}
|
||||
if (valueType.equals(Long.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySet(nullable, "bigint", DocPropertyType.LONG, ArrayElementConverter.LONG));
|
||||
}
|
||||
if (valueType.equals(Integer.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySet(nullable, "integer", DocPropertyType.INTEGER, ArrayElementConverter.INTEGER));
|
||||
}
|
||||
if (valueType.equals(Double.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySet(nullable, "float", DocPropertyType.DOUBLE, ArrayElementConverter.DOUBLE));
|
||||
}
|
||||
if (valueType.equals(String.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySet(nullable, "varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING));
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
}
|
||||
if (valueType.equals(Long.class)) {
|
||||
return LONG;
|
||||
}
|
||||
if (valueType.equals(Integer.class)) {
|
||||
return INTEGER;
|
||||
}
|
||||
if (valueType.equals(Double.class)) {
|
||||
return DOUBLE;
|
||||
}
|
||||
if (valueType.equals(String.class)) {
|
||||
return STRING;
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping on list");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public ScalarTypeArraySet typeForEnum(ScalarType<?> scalarType) {
|
||||
final String arrayType;
|
||||
switch (scalarType.getJdbcType()) {
|
||||
case Types.INTEGER:
|
||||
arrayType = "integer";
|
||||
break;
|
||||
case Types.VARCHAR:
|
||||
arrayType = "varchar";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("JdbcType [" + scalarType.getJdbcType() + "] not supported for @DbArray mapping on set.");
|
||||
}
|
||||
return new ScalarTypeArraySet(arrayType, scalarType.getDocType(), new ArrayElementConverter.EnumConverter(scalarType));
|
||||
public ScalarType<?> typeForEnum(ScalarType<?> scalarType, boolean nullable) {
|
||||
return new ScalarTypeArraySet(nullable, arrayTypeFor(scalarType), scalarType.getDocType(), new ArrayElementConverter.EnumConverter(scalarType));
|
||||
}
|
||||
}
|
||||
|
||||
private final String arrayType;
|
||||
|
||||
private final ArrayElementConverter<T> converter;
|
||||
private final ArrayElementConverter converter;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public ScalarTypeArraySet(String arrayType, DocPropertyType docPropertyType, ArrayElementConverter<T> converter) {
|
||||
super((Class) Set.class, Types.ARRAY, docPropertyType);
|
||||
public ScalarTypeArraySet(boolean nullable, String arrayType, DocPropertyType docPropertyType, ArrayElementConverter converter) {
|
||||
super(Set.class, Types.ARRAY, docPropertyType, nullable);
|
||||
this.arrayType = arrayType;
|
||||
this.converter = converter;
|
||||
}
|
||||
@@ -100,29 +91,38 @@ public class ScalarTypeArraySet<T> extends ScalarTypeArrayBase<Set<T>> implement
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<T> fromArray(Object[] array1) {
|
||||
Set<T> set = new LinkedHashSet<>();
|
||||
protected Set fromArray(Object[] array1) {
|
||||
Set set = new LinkedHashSet();
|
||||
for (Object element : array1) {
|
||||
set.add(converter.toElement(element));
|
||||
}
|
||||
return new ModifyAwareSet<>(set);
|
||||
return new ModifyAwareSet(set);
|
||||
}
|
||||
|
||||
protected Object[] toArray(Set<T> value) {
|
||||
protected Object[] toArray(Set value) {
|
||||
return converter.toDbArray(value.toArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBind bind, Set<T> value) throws SQLException {
|
||||
public void bind(DataBind bind, Set value) throws SQLException {
|
||||
if (value == null) {
|
||||
bind.setNull(Types.ARRAY);
|
||||
bindNull(bind);
|
||||
} else {
|
||||
bind.setArray(arrayType, toArray(value));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(Set<T> value) {
|
||||
protected void bindNull(DataBind bind) throws SQLException {
|
||||
if (nullable) {
|
||||
bind.setNull(Types.ARRAY);
|
||||
} else {
|
||||
bind.setArray(arrayType, toArray(EMPTY_SET));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(Set value) {
|
||||
try {
|
||||
return EJson.write(value);
|
||||
} catch (IOException e) {
|
||||
@@ -131,7 +131,7 @@ public class ScalarTypeArraySet<T> extends ScalarTypeArrayBase<Set<T>> implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<T> parse(String value) {
|
||||
public Set parse(String value) {
|
||||
try {
|
||||
return EJson.parseSet(value, false);
|
||||
} catch (IOException e) {
|
||||
@@ -140,12 +140,12 @@ public class ScalarTypeArraySet<T> extends ScalarTypeArrayBase<Set<T>> implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<T> jsonRead(JsonParser parser) throws IOException {
|
||||
public Set jsonRead(JsonParser parser) throws IOException {
|
||||
return EJson.parseSet(parser, parser.getCurrentToken());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator writer, Set<T> value) throws IOException {
|
||||
public void jsonWrite(JsonGenerator writer, Set value) throws IOException {
|
||||
EJson.write(value, writer);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,19 +5,18 @@ import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.util.Collections.EMPTY_SET;
|
||||
|
||||
/**
|
||||
* H2 database support for DB ARRAY.
|
||||
*/
|
||||
class ScalarTypeArraySetH2<T> extends ScalarTypeArraySet<T> {
|
||||
|
||||
private static final ScalarTypeArraySetH2<UUID> UUID = new ScalarTypeArraySetH2<>("uuid", DocPropertyType.UUID, ArrayElementConverter.UUID);
|
||||
private static final ScalarTypeArraySetH2<Long> LONG = new ScalarTypeArraySetH2<>("bigint", DocPropertyType.LONG, ArrayElementConverter.LONG);
|
||||
private static final ScalarTypeArraySetH2<Integer> INTEGER = new ScalarTypeArraySetH2<>("integer", DocPropertyType.INTEGER, ArrayElementConverter.INTEGER);
|
||||
private static final ScalarTypeArraySetH2<Double> DOUBLE = new ScalarTypeArraySetH2<>("double", DocPropertyType.DOUBLE, ArrayElementConverter.DOUBLE);
|
||||
private static final ScalarTypeArraySetH2<String> STRING = new ScalarTypeArraySetH2<>("varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING);
|
||||
@SuppressWarnings("rawtypes")
|
||||
class ScalarTypeArraySetH2 extends ScalarTypeArraySet {
|
||||
|
||||
static PlatformArrayTypeFactory factory() {
|
||||
return new ScalarTypeArraySetH2.Factory();
|
||||
@@ -25,47 +24,60 @@ class ScalarTypeArraySetH2<T> extends ScalarTypeArraySet<T> {
|
||||
|
||||
static class Factory implements PlatformArrayTypeFactory {
|
||||
|
||||
private final Map<String, ScalarTypeArraySetH2> cache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Return the ScalarType to use based on the List's generic parameter type.
|
||||
*/
|
||||
@Override
|
||||
public ScalarTypeArraySetH2<?> typeFor(Type valueType) {
|
||||
if (valueType.equals(java.util.UUID.class)) {
|
||||
return UUID;
|
||||
public ScalarType<?> typeFor(Type valueType, boolean nullable) {
|
||||
synchronized (this) {
|
||||
String key = valueType + ":" + nullable;
|
||||
if (valueType.equals(UUID.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySetH2(nullable, "uuid", DocPropertyType.UUID, ArrayElementConverter.UUID));
|
||||
}
|
||||
if (valueType.equals(Long.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySetH2(nullable, "bigint", DocPropertyType.LONG, ArrayElementConverter.LONG));
|
||||
}
|
||||
if (valueType.equals(Integer.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySetH2(nullable, "integer", DocPropertyType.INTEGER, ArrayElementConverter.INTEGER));
|
||||
}
|
||||
if (valueType.equals(Double.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySetH2(nullable, "float", DocPropertyType.DOUBLE, ArrayElementConverter.DOUBLE));
|
||||
}
|
||||
if (valueType.equals(String.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySetH2(nullable, "varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING));
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
}
|
||||
if (valueType.equals(Integer.class)) {
|
||||
return INTEGER;
|
||||
}
|
||||
if (valueType.equals(Long.class)) {
|
||||
return LONG;
|
||||
}
|
||||
if (valueType.equals(Double.class)) {
|
||||
return DOUBLE;
|
||||
}
|
||||
if (valueType.equals(String.class)) {
|
||||
return STRING;
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public ScalarTypeArraySetH2 typeForEnum(ScalarType<?> scalarType) {
|
||||
return new ScalarTypeArraySetH2("varchar", DocPropertyType.TEXT, new ArrayElementConverter.EnumConverter(scalarType));
|
||||
public ScalarType<?> typeForEnum(ScalarType<?> scalarType, boolean nullable) {
|
||||
return new ScalarTypeArraySetH2(nullable, "varchar", DocPropertyType.TEXT, new ArrayElementConverter.EnumConverter(scalarType));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private ScalarTypeArraySetH2(String arrayType, DocPropertyType docPropertyType, ArrayElementConverter converter) {
|
||||
super(arrayType, docPropertyType, converter);
|
||||
@SuppressWarnings("rawtypes")
|
||||
private ScalarTypeArraySetH2(boolean nullable, String arrayType, DocPropertyType docPropertyType, ArrayElementConverter converter) {
|
||||
super(nullable, arrayType, docPropertyType, converter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBind bind, Set<T> value) throws SQLException {
|
||||
public void bind(DataBind bind, Set value) throws SQLException {
|
||||
if (value == null) {
|
||||
bind.setNull(Types.ARRAY);
|
||||
bindNull(bind);
|
||||
} else {
|
||||
bind.setObject(toArray(value));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindNull(DataBind bind) throws SQLException {
|
||||
if (nullable) {
|
||||
bind.setNull(Types.ARRAY);
|
||||
} else {
|
||||
bind.setObject(toArray(EMPTY_SET));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,29 @@ import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
abstract class ScalarTypeJsonCollection<T> extends ScalarTypeBase<T> implements ScalarTypeArray {
|
||||
|
||||
protected DocPropertyType docPropertyType;
|
||||
protected final DocPropertyType docPropertyType;
|
||||
protected final boolean nullable;
|
||||
|
||||
public ScalarTypeJsonCollection(Class<T> type, int dbType, DocPropertyType docPropertyType) {
|
||||
public ScalarTypeJsonCollection(Class<T> type, int dbType, DocPropertyType docPropertyType, boolean nullable) {
|
||||
super(type, false, dbType);
|
||||
this.docPropertyType = docPropertyType;
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind null or empty list (when not nullable).
|
||||
*/
|
||||
protected void bindNull(DataBind bind) throws SQLException {
|
||||
if (nullable) {
|
||||
bind.setNull(Types.VARCHAR);
|
||||
} else {
|
||||
bind.setString("[]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,27 +17,28 @@ import java.util.List;
|
||||
* Types for mapping List in JSON format to DB types VARCHAR, JSON and JSONB.
|
||||
*/
|
||||
public class ScalarTypeJsonList {
|
||||
|
||||
/**
|
||||
* Return the appropriate ScalarType based requested dbType and if Postgres.
|
||||
*/
|
||||
public static ScalarType<?> typeFor(boolean postgres, int dbType, DocPropertyType docType) {
|
||||
public static ScalarType<?> typeFor(boolean postgres, int dbType, DocPropertyType docType, boolean nullable) {
|
||||
if (postgres) {
|
||||
switch (dbType) {
|
||||
case DbPlatformType.JSONB:
|
||||
return new ScalarTypeJsonList.JsonB(docType);
|
||||
return new ScalarTypeJsonList.JsonB(docType, nullable);
|
||||
case DbPlatformType.JSON:
|
||||
return new ScalarTypeJsonList.Json(docType);
|
||||
return new ScalarTypeJsonList.Json(docType, nullable);
|
||||
}
|
||||
}
|
||||
return new ScalarTypeJsonList.Varchar(docType);
|
||||
return new ScalarTypeJsonList.Varchar(docType, nullable);
|
||||
}
|
||||
|
||||
/**
|
||||
* List mapped to DB VARCHAR.
|
||||
*/
|
||||
public static class Varchar extends ScalarTypeJsonList.Base {
|
||||
public Varchar(DocPropertyType docType) {
|
||||
super(Types.VARCHAR, docType);
|
||||
public Varchar(DocPropertyType docType, boolean nullable) {
|
||||
super(Types.VARCHAR, docType, nullable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +46,8 @@ public class ScalarTypeJsonList {
|
||||
* List mapped to Postgres JSON.
|
||||
*/
|
||||
private static class Json extends ScalarTypeJsonList.PgBase {
|
||||
public Json(DocPropertyType docType) {
|
||||
super(DbPlatformType.JSON, PostgresHelper.JSON_TYPE, docType);
|
||||
public Json(DocPropertyType docType, boolean nullable) {
|
||||
super(DbPlatformType.JSON, PostgresHelper.JSON_TYPE, docType, nullable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +55,8 @@ public class ScalarTypeJsonList {
|
||||
* List mapped to Postgres JSONB.
|
||||
*/
|
||||
private static class JsonB extends ScalarTypeJsonList.PgBase {
|
||||
public JsonB(DocPropertyType docType) {
|
||||
super(DbPlatformType.JSONB, PostgresHelper.JSONB_TYPE, docType);
|
||||
public JsonB(DocPropertyType docType, boolean nullable) {
|
||||
super(DbPlatformType.JSONB, PostgresHelper.JSONB_TYPE, docType, nullable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,8 +66,8 @@ public class ScalarTypeJsonList {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private abstract static class Base extends ScalarTypeJsonCollection<List> {
|
||||
|
||||
public Base(int dbType, DocPropertyType docType) {
|
||||
super(List.class, dbType, docType);
|
||||
public Base(int dbType, DocPropertyType docType, boolean nullable) {
|
||||
super(List.class, dbType, docType, nullable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,21 +82,29 @@ public class ScalarTypeJsonList {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBind b, List value) throws SQLException {
|
||||
|
||||
public void bind(DataBind bind, List value) throws SQLException {
|
||||
if (value == null) {
|
||||
b.setNull(Types.VARCHAR);
|
||||
bindNull(bind);
|
||||
} else if (value.isEmpty()) {
|
||||
b.setString("[]");
|
||||
bind.setString("[]");
|
||||
} else {
|
||||
try {
|
||||
b.setString(EJson.write(value));
|
||||
bind.setString(EJson.write(value));
|
||||
} catch (IOException e) {
|
||||
throw new SQLException("Failed to format List into JSON content", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindNull(DataBind bind) throws SQLException {
|
||||
if (nullable) {
|
||||
bind.setNull(Types.VARCHAR);
|
||||
} else {
|
||||
bind.setString("[]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(List value) {
|
||||
try {
|
||||
@@ -123,7 +132,6 @@ public class ScalarTypeJsonList {
|
||||
public void jsonWrite(JsonGenerator writer, List value) throws IOException {
|
||||
EJson.write(value, writer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,17 +141,24 @@ public class ScalarTypeJsonList {
|
||||
|
||||
final String pgType;
|
||||
|
||||
PgBase(int jdbcType, String pgType, DocPropertyType docType) {
|
||||
super(jdbcType, docType);
|
||||
PgBase(int jdbcType, String pgType, DocPropertyType docType, boolean nullable) {
|
||||
super(jdbcType, docType, nullable);
|
||||
this.pgType = pgType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public void bind(DataBind bind, List value) throws SQLException {
|
||||
if (value == null) {
|
||||
bindNull(bind);
|
||||
} else {
|
||||
bind.setObject(PostgresHelper.asObject(pgType, formatValue(value)));
|
||||
}
|
||||
}
|
||||
|
||||
String rawJson = (value == null) ? null : formatValue(value);
|
||||
bind.setObject(PostgresHelper.asObject(pgType, rawJson));
|
||||
@Override
|
||||
protected void bindNull(DataBind bind) throws SQLException {
|
||||
bind.setObject(PostgresHelper.asObject(pgType, nullable ? null : "[]"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.text.TextException;
|
||||
import io.ebean.text.json.EJson;
|
||||
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;
|
||||
@@ -23,24 +23,24 @@ public class ScalarTypeJsonSet {
|
||||
/**
|
||||
* Return the appropriate ScalarType for the requested dbType and Postgres.
|
||||
*/
|
||||
public static ScalarType<?> typeFor(boolean postgres, int dbType, DocPropertyType docPropertyType) {
|
||||
public static ScalarType<?> typeFor(boolean postgres, int dbType, DocPropertyType docPropertyType, boolean nullable) {
|
||||
if (postgres) {
|
||||
switch (dbType) {
|
||||
case DbPlatformType.JSONB:
|
||||
return new ScalarTypeJsonSet.JsonB(docPropertyType);
|
||||
return new ScalarTypeJsonSet.JsonB(docPropertyType, nullable);
|
||||
case DbPlatformType.JSON:
|
||||
return new ScalarTypeJsonSet.Json(docPropertyType);
|
||||
return new ScalarTypeJsonSet.Json(docPropertyType, nullable);
|
||||
}
|
||||
}
|
||||
return new ScalarTypeJsonSet.Varchar(docPropertyType);
|
||||
return new ScalarTypeJsonSet.Varchar(docPropertyType, nullable);
|
||||
}
|
||||
|
||||
/**
|
||||
* List mapped to DB VARCHAR.
|
||||
*/
|
||||
public static class Varchar extends ScalarTypeJsonSet.Base {
|
||||
public Varchar(DocPropertyType docPropertyType) {
|
||||
super(Types.VARCHAR, docPropertyType);
|
||||
public Varchar(DocPropertyType docPropertyType, boolean nullable) {
|
||||
super(Types.VARCHAR, docPropertyType, nullable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ public class ScalarTypeJsonSet {
|
||||
* List mapped to Postgres JSON.
|
||||
*/
|
||||
private static class Json extends ScalarTypeJsonSet.PgBase {
|
||||
public Json(DocPropertyType docPropertyType) {
|
||||
super(DbPlatformType.JSON, PostgresHelper.JSON_TYPE, docPropertyType);
|
||||
public Json(DocPropertyType docPropertyType, boolean nullable) {
|
||||
super(DbPlatformType.JSON, PostgresHelper.JSON_TYPE, docPropertyType, nullable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ public class ScalarTypeJsonSet {
|
||||
* List mapped to Postgres JSONB.
|
||||
*/
|
||||
private static class JsonB extends ScalarTypeJsonSet.PgBase {
|
||||
public JsonB(DocPropertyType docPropertyType) {
|
||||
super(DbPlatformType.JSONB, PostgresHelper.JSONB_TYPE, docPropertyType);
|
||||
public JsonB(DocPropertyType docPropertyType, boolean nullable) {
|
||||
super(DbPlatformType.JSONB, PostgresHelper.JSONB_TYPE, docPropertyType, nullable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ public class ScalarTypeJsonSet {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private abstract static class Base extends ScalarTypeJsonCollection<Set> {
|
||||
|
||||
public Base(int dbType, DocPropertyType docPropertyType) {
|
||||
super(Set.class, dbType, docPropertyType);
|
||||
public Base(int dbType, DocPropertyType docPropertyType, boolean nullable) {
|
||||
super(Set.class, dbType, docPropertyType, nullable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,21 +84,29 @@ public class ScalarTypeJsonSet {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBind b, Set value) throws SQLException {
|
||||
|
||||
public void bind(DataBind bind, Set value) throws SQLException {
|
||||
if (value == null) {
|
||||
b.setNull(Types.VARCHAR);
|
||||
bindNull(bind);
|
||||
} else if (value.isEmpty()) {
|
||||
b.setString("[]");
|
||||
bind.setString("[]");
|
||||
} else {
|
||||
try {
|
||||
b.setString(EJson.write(value));
|
||||
bind.setString(EJson.write(value));
|
||||
} catch (IOException e) {
|
||||
throw new SQLException("Failed to format Set into JSON content", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindNull(DataBind bind) throws SQLException {
|
||||
if (nullable) {
|
||||
bind.setNull(Types.VARCHAR);
|
||||
} else {
|
||||
bind.setString("[]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(Set value) {
|
||||
try {
|
||||
@@ -140,17 +148,24 @@ public class ScalarTypeJsonSet {
|
||||
|
||||
final String pgType;
|
||||
|
||||
PgBase(int jdbcType, String pgType, DocPropertyType docPropertyType) {
|
||||
super(jdbcType, docPropertyType);
|
||||
PgBase(int jdbcType, String pgType, DocPropertyType docPropertyType, boolean nullable) {
|
||||
super(jdbcType, docPropertyType, nullable);
|
||||
this.pgType = pgType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public void bind(DataBind bind, Set value) throws SQLException {
|
||||
if (value == null) {
|
||||
bindNull(bind);
|
||||
} else {
|
||||
bind.setObject(PostgresHelper.asObject(pgType, formatValue(value)));
|
||||
}
|
||||
}
|
||||
|
||||
String rawJson = (value == null) ? null : formatValue(value);
|
||||
bind.setObject(PostgresHelper.asObject(pgType, rawJson));
|
||||
@Override
|
||||
protected void bindNull(DataBind bind) throws SQLException {
|
||||
bind.setObject(PostgresHelper.asObject(pgType, nullable ? null : "[]"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ public interface TypeManager {
|
||||
/**
|
||||
* Return the ScalarType used to handle DB ARRAY.
|
||||
*/
|
||||
ScalarType<?> getArrayScalarType(Class<?> type, DbArray dbArray, Type genericType);
|
||||
ScalarType<?> getArrayScalarType(Class<?> type, DbArray dbArray, Type genericType, boolean nullable);
|
||||
|
||||
/**
|
||||
* Return the ScalarType used to handle HSTORE (Map<String,String>).
|
||||
|
||||
Reference in New Issue
Block a user