mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-23 01:07:49 +00:00
Merge pull request #2826 from ebean-orm/feature/json-node-module
Refactor extract ebean-jackson-jsonnode module - support for Jackson JsonNode (into separate module)
This commit is contained in:
@@ -31,6 +31,12 @@
|
||||
<version>13.9.4-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.9.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource</artifactId>
|
||||
|
||||
@@ -116,6 +116,12 @@
|
||||
<version>13.9.4-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.9.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
|
||||
@@ -26,6 +26,14 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided scope for Postgres JSON/JSONB support -->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.4.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
||||
+14
-3
@@ -1,5 +1,7 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
package io.ebean.core.type;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import org.postgresql.util.PGobject;
|
||||
|
||||
import java.sql.SQLException;
|
||||
@@ -9,12 +11,12 @@ public final class PostgresHelper {
|
||||
/**
|
||||
* The Postgres JSON DB type.
|
||||
*/
|
||||
static final String JSON_TYPE = "json";
|
||||
public static final String JSON_TYPE = "json";
|
||||
|
||||
/**
|
||||
* The Postgres JSONB DB type.
|
||||
*/
|
||||
static final String JSONB_TYPE = "jsonb";
|
||||
public static final String JSONB_TYPE = "jsonb";
|
||||
|
||||
static final String INET_TYPE = "inet";
|
||||
|
||||
@@ -31,4 +33,13 @@ public final class PostgresHelper {
|
||||
pgo.setValue(rawJson);
|
||||
return pgo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the platform is Postgres or compatible like Yugabyte, Cockroach.
|
||||
*/
|
||||
public static boolean isPostgresCompatible(DatabasePlatform databasePlatform) {
|
||||
return databasePlatform.isPlatform(Platform.POSTGRES)
|
||||
|| databasePlatform.isPlatform(Platform.YUGABYTE)
|
||||
|| databasePlatform.isPlatform(Platform.COCKROACH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package io.ebean.core.type;
|
||||
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
/**
|
||||
* A ScalarType that has variations based on the mapped JDBC type (like VARCHAR, CLOB, JSON etc).
|
||||
*/
|
||||
public interface ScalarTypeSet<T> {
|
||||
|
||||
/**
|
||||
* The property type these scalar types map to.
|
||||
*/
|
||||
Class<?> type();
|
||||
|
||||
/**
|
||||
* Return a default ScalarType to use when no other annotations like {@code @DbJson} are present.
|
||||
*/
|
||||
@Nullable
|
||||
ScalarType<?> defaultType();
|
||||
|
||||
/**
|
||||
* Return the scalarType to use for the given jdbc type.
|
||||
* <p>
|
||||
* For example VARCHAR, CLOB, JSON etc.
|
||||
*/
|
||||
ScalarType<T> forType(int jdbcType);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.ebean.core.type;
|
||||
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
|
||||
/**
|
||||
* Factory to create ScalarTypeSet.
|
||||
*/
|
||||
public interface ScalarTypeSetFactory {
|
||||
|
||||
/**
|
||||
* Create the ScalarTypeSet given the config and optional objectMapper.
|
||||
*/
|
||||
@Nullable
|
||||
ScalarTypeSet<?> createTypeSet(DatabaseConfig config, @Nullable Object objectMapper);
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ module io.ebean.core.type {
|
||||
|
||||
requires transitive java.sql;
|
||||
requires transitive io.ebean.api;
|
||||
requires static org.postgresql.jdbc;
|
||||
|
||||
requires static com.fasterxml.jackson.core;
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
this.dbIdentity = config.getDatabasePlatform().dbIdentity();
|
||||
this.deplyInherit = config.getDeployInherit();
|
||||
this.deployUtil = config.getDeployUtil();
|
||||
this.typeManager = deployUtil.getTypeManager();
|
||||
this.typeManager = deployUtil.typeManager();
|
||||
this.beanManagerFactory = new BeanManagerFactory(config.getDatabasePlatform());
|
||||
this.beanLifecycleAdapterFactory = new BeanLifecycleAdapterFactory(this.config);
|
||||
this.persistControllerManager = new PersistControllerManager(bootupClasses);
|
||||
@@ -184,12 +184,12 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
|
||||
@Override
|
||||
public ScalarType<?> scalarType(String cast) {
|
||||
return typeManager.getScalarType(cast);
|
||||
return typeManager.type(cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> scalarType(int jdbcType) {
|
||||
return typeManager.getScalarType(jdbcType);
|
||||
return typeManager.type(jdbcType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -884,7 +884,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
private void makeOrderColumn(DeployBeanPropertyAssocMany<?> oneToMany) {
|
||||
DeployBeanDescriptor<?> targetDesc = targetDescriptor(oneToMany);
|
||||
DeployOrderColumn orderColumn = oneToMany.getOrderColumn();
|
||||
final ScalarType<?> scalarType = typeManager.getScalarType(Integer.class);
|
||||
final ScalarType<?> scalarType = typeManager.type(Integer.class);
|
||||
DeployBeanProperty orderProperty = new DeployBeanProperty(targetDesc, Integer.class, scalarType, null);
|
||||
orderProperty.setName(DeployOrderColumn.LOGICAL_NAME);
|
||||
orderProperty.setDbColumn(orderColumn.getName());
|
||||
|
||||
+3
-3
@@ -222,7 +222,7 @@ final class AnnotationAssocManys extends AnnotationAssoc {
|
||||
dbKeyColumn = mapKeyColumn.name();
|
||||
}
|
||||
|
||||
ScalarType<?> keyScalarType = util.getTypeManager().getScalarType(prop.getMapKeyType());
|
||||
ScalarType<?> keyScalarType = util.typeManager().type(prop.getMapKeyType());
|
||||
|
||||
DeployBeanProperty keyProp = new DeployBeanProperty(elementDescriptor, elementType, keyScalarType, null);
|
||||
setElementProperty(keyProp, "key", dbKeyColumn, sortOrder++);
|
||||
@@ -234,10 +234,10 @@ final class AnnotationAssocManys extends AnnotationAssoc {
|
||||
}
|
||||
}
|
||||
|
||||
ScalarType<?> valueScalarType = util.getTypeManager().getScalarType(elementType);
|
||||
ScalarType<?> valueScalarType = util.typeManager().type(elementType);
|
||||
if (valueScalarType == null && elementType.isEnum()) {
|
||||
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>)elementType;
|
||||
valueScalarType = util.getTypeManager().createEnumScalarType(enumClass, EnumType.STRING);
|
||||
valueScalarType = util.typeManager().enumType(enumClass, EnumType.STRING);
|
||||
}
|
||||
|
||||
boolean scalar = true;
|
||||
|
||||
@@ -52,9 +52,9 @@ abstract class AnnotationBase {
|
||||
|
||||
AnnotationBase(DeployUtil util) {
|
||||
this.util = util;
|
||||
this.databasePlatform = util.getDbPlatform();
|
||||
this.databasePlatform = util.dbPlatform();
|
||||
this.platform = databasePlatform.platform();
|
||||
this.namingConvention = util.getNamingConvention();
|
||||
this.namingConvention = util.namingConvention();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -301,7 +301,7 @@ final class AnnotationFields extends AnnotationParser {
|
||||
|
||||
private void initEncrypt(DeployBeanProperty prop) {
|
||||
if (!prop.isTransient()) {
|
||||
EncryptDeploy encryptDeploy = util.getEncryptDeploy(info.getDescriptor().getBaseTableFull(), prop.getDbColumn());
|
||||
EncryptDeploy encryptDeploy = util.encryptDeploy(info.getDescriptor().getBaseTableFull(), prop.getDbColumn());
|
||||
if (encryptDeploy == null || encryptDeploy.getMode() == Mode.MODE_ANNOTATION) {
|
||||
Encrypted encrypted = get(prop, Encrypted.class);
|
||||
if (encrypted != null) {
|
||||
@@ -398,7 +398,7 @@ final class AnnotationFields extends AnnotationParser {
|
||||
return;
|
||||
}
|
||||
if (dbEncString) {
|
||||
DbEncrypt dbEncrypt = util.getDbPlatform().dbEncrypt();
|
||||
DbEncrypt dbEncrypt = util.dbPlatform().dbEncrypt();
|
||||
if (dbEncrypt != null) {
|
||||
// check if we have a DB encryption function for this type
|
||||
int jdbcType = prop.getScalarType().jdbcType();
|
||||
@@ -427,7 +427,7 @@ final class AnnotationFields extends AnnotationParser {
|
||||
|
||||
private ScalarTypeBytesBase getDbEncryptType(DeployBeanProperty prop) {
|
||||
int dbType = prop.isLob() ? Types.BLOB : Types.VARBINARY;
|
||||
return (ScalarTypeBytesBase) util.getTypeManager().getScalarType(dbType);
|
||||
return (ScalarTypeBytesBase) util.typeManager().type(dbType);
|
||||
}
|
||||
|
||||
private DataEncryptSupport createDataEncryptSupport(DeployBeanProperty prop) {
|
||||
|
||||
+2
-2
@@ -108,7 +108,7 @@ public final class DeployCreateProperties {
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
|
||||
try {
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(targetType);
|
||||
ScalarType<?> scalarType = typeManager.type(targetType);
|
||||
if (scalarType != null) {
|
||||
return new DeployBeanPropertySimpleCollection(desc, targetType, manyType);
|
||||
}
|
||||
@@ -141,7 +141,7 @@ public final class DeployCreateProperties {
|
||||
if (propertyType.isEnum() || propertyType.isPrimitive()) {
|
||||
return new DeployBeanProperty(desc, propertyType, null, null);
|
||||
}
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(propertyType);
|
||||
ScalarType<?> scalarType = typeManager.type(propertyType);
|
||||
if (scalarType != null) {
|
||||
return new DeployBeanProperty(desc, propertyType, scalarType, null);
|
||||
}
|
||||
|
||||
@@ -60,15 +60,15 @@ public final class DeployUtil {
|
||||
this.useValidationNotNull = config.isUseValidationNotNull();
|
||||
}
|
||||
|
||||
public TypeManager getTypeManager() {
|
||||
public TypeManager typeManager() {
|
||||
return typeManager;
|
||||
}
|
||||
|
||||
public DatabasePlatform getDbPlatform() {
|
||||
public DatabasePlatform dbPlatform() {
|
||||
return dbPlatform;
|
||||
}
|
||||
|
||||
public NamingConvention getNamingConvention() {
|
||||
public NamingConvention namingConvention() {
|
||||
return namingConvention;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public final class DeployUtil {
|
||||
}
|
||||
}
|
||||
|
||||
EncryptDeploy getEncryptDeploy(TableName table, String column) {
|
||||
EncryptDeploy encryptDeploy(TableName table, String column) {
|
||||
if (encryptDeployManager == null) {
|
||||
return EncryptDeploy.ANNOTATION;
|
||||
}
|
||||
@@ -102,7 +102,7 @@ public final class DeployUtil {
|
||||
try {
|
||||
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) enumType;
|
||||
EnumType type = enumerated != null ? enumerated.value() : null;
|
||||
ScalarType<?> scalarType = typeManager.createEnumScalarType(enumClass, type);
|
||||
ScalarType<?> scalarType = typeManager.enumType(enumClass, type);
|
||||
prop.setScalarType(scalarType);
|
||||
prop.setDbType(scalarType.jdbcType());
|
||||
} catch (IllegalStateException e) {
|
||||
@@ -123,7 +123,7 @@ public final class DeployUtil {
|
||||
// this will be an Enum type...
|
||||
return;
|
||||
}
|
||||
ScalarType<?> scalarType = getScalarType(property);
|
||||
ScalarType<?> scalarType = scalarType(property);
|
||||
if (scalarType != null) {
|
||||
// set the jdbc type this maps to
|
||||
property.setDbType(scalarType.jdbcType());
|
||||
@@ -132,12 +132,12 @@ public final class DeployUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private ScalarType<?> getScalarType(DeployBeanProperty property) {
|
||||
private ScalarType<?> scalarType(DeployBeanProperty property) {
|
||||
// Note that Temporal types already have dbType
|
||||
// set via annotations
|
||||
Class<?> propType = property.getPropertyType();
|
||||
try {
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(propType, property.getDbType());
|
||||
ScalarType<?> scalarType = typeManager.type(propType, property.getDbType());
|
||||
if (scalarType != null || property.isTransient()) {
|
||||
return scalarType;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ public final class DeployUtil {
|
||||
* Map to Postgres HSTORE type (with fallback to JSON storage in VARCHAR).
|
||||
*/
|
||||
void setDbMap(DeployBeanProperty prop, DbMap dbMap) {
|
||||
ScalarType<?> scalarType = typeManager.getDbMapScalarType();
|
||||
ScalarType<?> scalarType = typeManager.dbMapType();
|
||||
int dbType = scalarType.jdbcType();
|
||||
prop.setDbType(dbType);
|
||||
prop.setScalarType(scalarType);
|
||||
@@ -177,7 +177,7 @@ public final class DeployUtil {
|
||||
prop.setNullable(false);
|
||||
}
|
||||
Class<?> type = prop.getPropertyType();
|
||||
ScalarType<?> scalarType = typeManager.getArrayScalarType(type, prop.getGenericType(), prop.isNullable());
|
||||
ScalarType<?> scalarType = typeManager.dbArrayType(type, prop.getGenericType(), prop.isNullable());
|
||||
if (scalarType == null) {
|
||||
throw new RuntimeException("No ScalarType for @DbArray type for " + prop.getFullBeanName());
|
||||
}
|
||||
@@ -198,7 +198,7 @@ public final class DeployUtil {
|
||||
}
|
||||
|
||||
void setDbJsonType(DeployBeanProperty prop, DbJson dbJsonType) {
|
||||
int dbType = getDbJsonStorage(dbJsonType.storage());
|
||||
int dbType = dbJsonStorage(dbJsonType.storage());
|
||||
setDbJsonType(prop, dbType, dbJsonType.length(), dbJsonType.mutationDetection());
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ public final class DeployUtil {
|
||||
private void setDbJsonType(DeployBeanProperty prop, int dbType, int dbLength, MutationDetection mutationDetection) {
|
||||
prop.setDbType(dbType);
|
||||
prop.setMutationDetection(mutationDetection);
|
||||
ScalarType<?> scalarType = typeManager.getJsonScalarType(prop, dbType, dbLength);
|
||||
ScalarType<?> scalarType = typeManager.dbJsonType(prop, dbType, dbLength);
|
||||
if (scalarType == null) {
|
||||
throw new RuntimeException("No ScalarType for JSON property " + prop + " dbType:" + dbType);
|
||||
}
|
||||
@@ -224,7 +224,7 @@ public final class DeployUtil {
|
||||
/**
|
||||
* Return the JDBC type for the JSON storage type.
|
||||
*/
|
||||
private int getDbJsonStorage(DbJsonType dbJsonType) {
|
||||
private int dbJsonStorage(DbJsonType dbJsonType) {
|
||||
switch (dbJsonType) {
|
||||
case JSONB:
|
||||
return DbPlatformType.JSONB;
|
||||
@@ -253,7 +253,7 @@ public final class DeployUtil {
|
||||
// this also sets the lob flag on DeployBeanProperty
|
||||
int lobType = isClobType(type) ? dbCLOBType : dbBLOBType;
|
||||
|
||||
scalarType = typeManager.getScalarType(type, lobType);
|
||||
scalarType = typeManager.type(type, lobType);
|
||||
if (scalarType == null) {
|
||||
// this should never occur actually
|
||||
throw new RuntimeException("No ScalarType for LOB type " + type + " dbType:" + lobType);
|
||||
|
||||
@@ -21,7 +21,7 @@ final class DtoMetaConstructor {
|
||||
this.types = constructor.getParameterTypes();
|
||||
this.scalarTypes = new ScalarType[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
scalarTypes[i] = typeManager.getScalarType(types[i]);
|
||||
scalarTypes[i] = typeManager.type(types[i]);
|
||||
}
|
||||
this.handle = LOOKUP.findConstructor(someClass, typeFor(types));
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ final class DtoMetaProperty implements DtoReadSet {
|
||||
this.name = name;
|
||||
if (writeMethod != null) {
|
||||
this.setter = lookupMethodHandle(dtoType, writeMethod);
|
||||
this.scalarType = typeManager.getScalarType(propertyType(writeMethod), propertyClass(writeMethod));
|
||||
this.scalarType = typeManager.type(propertyType(writeMethod), propertyClass(writeMethod));
|
||||
} else {
|
||||
this.scalarType = null;
|
||||
this.setter = null;
|
||||
|
||||
@@ -36,7 +36,7 @@ public final class DJsonScalar {
|
||||
gen.writeRaw(']');
|
||||
|
||||
} else {
|
||||
ScalarType scalarType = typeManager.getScalarType(value.getClass());
|
||||
ScalarType scalarType = typeManager.type(value.getClass());
|
||||
if (scalarType == null) {
|
||||
throw new IllegalArgumentException("unhandled type " + value.getClass());
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.persist;
|
||||
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.core.type.DataReader;
|
||||
import io.ebean.core.type.PostgresHelper;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebeaninternal.api.BindParams;
|
||||
import io.ebeaninternal.api.CoreLog;
|
||||
@@ -37,7 +38,7 @@ public final class Binder {
|
||||
public Binder(TypeManager typeManager, SpiLogManager logManager, int asOfBindCount, boolean asOfStandardsBased,
|
||||
DbExpressionHandler dbExpressionHandler, DataTimeZone dataTimeZone, MultiValueBind multiValueBind) {
|
||||
this.typeManager = typeManager;
|
||||
this.geoTypeBinder = typeManager.getGeoTypeBinder();
|
||||
this.geoTypeBinder = typeManager.geoTypeBinder();
|
||||
this.asOfBindCount = asOfBindCount;
|
||||
this.asOfStandardsBased = asOfStandardsBased;
|
||||
this.dbExpressionHandler = dbExpressionHandler;
|
||||
@@ -153,7 +154,7 @@ public final class Binder {
|
||||
}
|
||||
|
||||
public ScalarType<?> getScalarType(Class<?> clazz) {
|
||||
ScalarType<?> type = typeManager.getScalarType(clazz);
|
||||
ScalarType<?> type = typeManager.type(clazz);
|
||||
if (type == null) {
|
||||
throw new PersistenceException("No ScalarType registered for " + clazz);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.ebean.annotation.*;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
@@ -9,9 +8,7 @@ import io.ebean.config.PlatformConfig;
|
||||
import io.ebean.config.ScalarTypeConverter;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.core.type.DocPropertyType;
|
||||
import io.ebean.core.type.ExtraTypeFactory;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.core.type.*;
|
||||
import io.ebean.types.Cidr;
|
||||
import io.ebean.types.Inet;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
@@ -40,6 +37,7 @@ import java.time.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static io.ebean.core.type.PostgresHelper.isPostgresCompatible;
|
||||
import static java.lang.System.Logger.Level.*;
|
||||
|
||||
/**
|
||||
@@ -51,6 +49,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
|
||||
private static final System.Logger log = CoreLog.internal;
|
||||
|
||||
private final Map<Class<?>, ScalarTypeSet<?>> typeSets = new HashMap<>();
|
||||
private final ConcurrentHashMap<Class<?>, ScalarType<?>> typeMap;
|
||||
private final ConcurrentHashMap<Integer, ScalarType<?>> nativeMap;
|
||||
private final ConcurrentHashMap<String, ScalarType<?>> logicalMap;
|
||||
@@ -71,29 +70,6 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
private final EnumType defaultEnumType;
|
||||
private final DatabasePlatform databasePlatform;
|
||||
|
||||
// OPTIONAL ScalarTypes registered if Jackson/JsonNode is in the classpath
|
||||
|
||||
/**
|
||||
* Jackson's JsonNode storage to Clob.
|
||||
*/
|
||||
private ScalarType<?> jsonNodeClob;
|
||||
/**
|
||||
* Jackson's JsonNode storage to Blob.
|
||||
*/
|
||||
private ScalarType<?> jsonNodeBlob;
|
||||
/**
|
||||
* Jackson's JsonNode storage to Varchar.
|
||||
*/
|
||||
private ScalarType<?> jsonNodeVarchar;
|
||||
/**
|
||||
* Jackson's JsonNode storage to Postgres JSON or Clob.
|
||||
*/
|
||||
private ScalarType<?> jsonNodeJson;
|
||||
/**
|
||||
* Jackson's JsonNode storage to Postgres JSONB or Clob.
|
||||
*/
|
||||
private ScalarType<?> jsonNodeJsonb;
|
||||
|
||||
private final PlatformArrayTypeFactory arrayTypeListFactory;
|
||||
private final PlatformArrayTypeFactory arrayTypeSetFactory;
|
||||
private GeoTypeBinder geoTypeBinder;
|
||||
@@ -120,7 +96,6 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
|
||||
initialiseStandard(config);
|
||||
initialiseJavaTimeTypes(config);
|
||||
initialiseJacksonTypes();
|
||||
loadTypesFromProviders(config, objectMapper);
|
||||
loadGeoTypeBinder(config);
|
||||
|
||||
@@ -160,22 +135,21 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
* Load custom scalar types registered via ExtraTypeFactory and ServiceLoader.
|
||||
*/
|
||||
private void loadTypesFromProviders(DatabaseConfig config, Object objectMapper) {
|
||||
ServiceLoader<ExtraTypeFactory> factories = ServiceLoader.load(ExtraTypeFactory.class);
|
||||
Iterator<ExtraTypeFactory> iterator = factories.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
// use the cacheFactory (via classpath service loader)
|
||||
ExtraTypeFactory plugin = iterator.next();
|
||||
List<? extends ScalarType<?>> types = plugin.createTypes(config, objectMapper);
|
||||
for (ScalarType<?> type : types) {
|
||||
for (ExtraTypeFactory plugin : ServiceLoader.load(ExtraTypeFactory.class)) {
|
||||
for (ScalarType<?> type : plugin.createTypes(config, objectMapper)) {
|
||||
add(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPostgresCompatible(DatabasePlatform databasePlatform) {
|
||||
return databasePlatform.isPlatform(Platform.POSTGRES)
|
||||
|| databasePlatform.isPlatform(Platform.YUGABYTE)
|
||||
|| databasePlatform.isPlatform(Platform.COCKROACH);
|
||||
for (ScalarTypeSetFactory factory : ServiceLoader.load(ScalarTypeSetFactory.class)) {
|
||||
ScalarTypeSet<?> typeSet = factory.createTypeSet(config, objectMapper);
|
||||
if (typeSet != null) {
|
||||
typeSets.put(typeSet.type(), typeSet);
|
||||
ScalarType<?> defaultType = typeSet.defaultType();
|
||||
if (defaultType != null) {
|
||||
typeMap.put(typeSet.type(), defaultType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hstoreSupport() {
|
||||
@@ -185,8 +159,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
/**
|
||||
* Register a custom ScalarType.
|
||||
*/
|
||||
@Override
|
||||
public void add(ScalarType<?> scalarType) {
|
||||
private void add(ScalarType<?> scalarType) {
|
||||
typeMap.put(scalarType.type(), scalarType);
|
||||
logAdd(scalarType);
|
||||
}
|
||||
@@ -198,7 +171,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> getScalarType(String cast) {
|
||||
public ScalarType<?> type(String cast) {
|
||||
return logicalMap.get(cast);
|
||||
}
|
||||
|
||||
@@ -206,27 +179,27 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
* Return the ScalarType for the given jdbc type as per java.sql.Types.
|
||||
*/
|
||||
@Override
|
||||
public ScalarType<?> getScalarType(int jdbcType) {
|
||||
public ScalarType<?> type(int jdbcType) {
|
||||
return nativeMap.get(jdbcType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> getScalarType(Type propertyType, Class<?> propertyClass) {
|
||||
public ScalarType<?> type(Type propertyType, Class<?> propertyClass) {
|
||||
if (propertyType instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType)propertyType;
|
||||
ParameterizedType pt = (ParameterizedType) propertyType;
|
||||
Type rawType = pt.getRawType();
|
||||
if (List.class == rawType || Set.class == rawType) {
|
||||
return getArrayScalarType((Class<?>)rawType, propertyType, true);
|
||||
return dbArrayType((Class<?>) rawType, propertyType, true);
|
||||
}
|
||||
}
|
||||
return getScalarType(propertyClass);
|
||||
return type(propertyClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* This can return null if no matching ScalarType is found.
|
||||
*/
|
||||
@Override
|
||||
public ScalarType<?> getScalarType(Class<?> type) {
|
||||
public ScalarType<?> type(Class<?> type) {
|
||||
ScalarType<?> found = typeMap.get(type);
|
||||
if (found == null) {
|
||||
if (type.getName().equals("org.joda.time.LocalTime")) {
|
||||
@@ -260,7 +233,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
return found;
|
||||
}
|
||||
// second step - loop through interfaces of this type
|
||||
for (Class<?> iface: parent.getInterfaces()) {
|
||||
for (Class<?> iface : parent.getInterfaces()) {
|
||||
found = checkInheritedTypes(iface);
|
||||
if (found != null && found != ScalarTypeNotFound.INSTANCE) {
|
||||
typeMap.put(type, found); // store type for next lookup
|
||||
@@ -274,37 +247,37 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeoTypeBinder getGeoTypeBinder() {
|
||||
public GeoTypeBinder geoTypeBinder() {
|
||||
return geoTypeBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> getDbMapScalarType() {
|
||||
public ScalarType<?> dbMapType() {
|
||||
return hstoreSupport() ? hstoreType : ScalarTypeJsonMap.typeFor(false, Types.VARCHAR, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> getArrayScalarType(Class<?> type, Type genericType, boolean nullable) {
|
||||
Type valueType = getValueType(genericType);
|
||||
public ScalarType<?> dbArrayType(Class<?> type, Type genericType, boolean nullable) {
|
||||
Type valueType = valueType(genericType);
|
||||
if (type.equals(List.class)) {
|
||||
return getArrayScalarTypeList(valueType, nullable);
|
||||
return dbArrayTypeList(valueType, nullable);
|
||||
} else if (type.equals(Set.class)) {
|
||||
return getArrayScalarTypeSet(valueType, nullable);
|
||||
return dbArrayTypeSet(valueType, nullable);
|
||||
} else {
|
||||
throw new IllegalStateException("@DbArray does not support type " + type);
|
||||
}
|
||||
}
|
||||
|
||||
private ScalarType<?> getArrayScalarTypeSet(Type valueType, boolean nullable) {
|
||||
private ScalarType<?> dbArrayTypeSet(Type valueType, boolean nullable) {
|
||||
if (isEnumType(valueType)) {
|
||||
return arrayTypeSetFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), null), nullable);
|
||||
return arrayTypeSetFactory.typeForEnum(enumType(asEnumClass(valueType), null), nullable);
|
||||
}
|
||||
return arrayTypeSetFactory.typeFor(valueType, nullable);
|
||||
}
|
||||
|
||||
private ScalarType<?> getArrayScalarTypeList(Type valueType, boolean nullable) {
|
||||
private ScalarType<?> dbArrayTypeList(Type valueType, boolean nullable) {
|
||||
if (isEnumType(valueType)) {
|
||||
return arrayTypeListFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), null), nullable);
|
||||
return arrayTypeListFactory.typeForEnum(enumType(asEnumClass(valueType), null), nullable);
|
||||
}
|
||||
return arrayTypeListFactory.typeFor(valueType, nullable);
|
||||
}
|
||||
@@ -318,7 +291,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> getJsonScalarType(DeployBeanProperty prop, int dbType, int dbLength) {
|
||||
public ScalarType<?> dbJsonType(DeployBeanProperty prop, int dbType, int dbLength) {
|
||||
Class<?> type = prop.getPropertyType();
|
||||
Type genericType = prop.getGenericType();
|
||||
boolean hasJacksonAnnotations = objectMapperPresent && checkJacksonAnnotations(prop);
|
||||
@@ -327,7 +300,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
return ScalarTypeJsonString.typeFor(postgres, dbType);
|
||||
}
|
||||
if (type.equals(List.class)) {
|
||||
DocPropertyType docType = getDocType(genericType);
|
||||
DocPropertyType docType = docType(genericType);
|
||||
if (!hasJacksonAnnotations && isValueTypeSimple(genericType)) {
|
||||
return ScalarTypeJsonList.typeFor(postgres, dbType, docType, prop.isNullable(), jsonManager.keepSource(prop));
|
||||
} else {
|
||||
@@ -335,7 +308,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
}
|
||||
if (type.equals(Set.class)) {
|
||||
DocPropertyType docType = getDocType(genericType);
|
||||
DocPropertyType docType = docType(genericType);
|
||||
if (!hasJacksonAnnotations && isValueTypeSimple(genericType)) {
|
||||
return ScalarTypeJsonSet.typeFor(postgres, dbType, docType, prop.isNullable(), jsonManager.keepSource(prop));
|
||||
} else {
|
||||
@@ -350,19 +323,9 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
}
|
||||
if (objectMapperPresent && prop.getMutationDetection() == MutationDetection.DEFAULT) {
|
||||
if (type.equals(JsonNode.class)) {
|
||||
switch (dbType) {
|
||||
case Types.VARCHAR:
|
||||
return jsonNodeVarchar;
|
||||
case Types.BLOB:
|
||||
return jsonNodeBlob;
|
||||
case Types.CLOB:
|
||||
return jsonNodeClob;
|
||||
case DbPlatformType.JSONB:
|
||||
return jsonNodeJsonb;
|
||||
default:
|
||||
return jsonNodeJson;
|
||||
}
|
||||
ScalarTypeSet<?> typeSet = typeSets.get(type);
|
||||
if (typeSet != null) {
|
||||
return typeSet.forType(dbType);
|
||||
}
|
||||
}
|
||||
return createJsonObjectMapperType(prop, dbType, DocPropertyType.OBJECT);
|
||||
@@ -376,9 +339,9 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
return prop.getMetaAnnotation(com.fasterxml.jackson.annotation.JacksonAnnotation.class) != null;
|
||||
}
|
||||
|
||||
private DocPropertyType getDocType(Type genericType) {
|
||||
private DocPropertyType docType(Type genericType) {
|
||||
if (genericType instanceof Class<?>) {
|
||||
ScalarType<?> found = getScalarType((Class<?>)genericType);
|
||||
ScalarType<?> found = type((Class<?>) genericType);
|
||||
if (found != null) {
|
||||
return found.docType();
|
||||
}
|
||||
@@ -394,7 +357,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
return String.class.equals(typeArg) || Long.class.equals(typeArg);
|
||||
}
|
||||
|
||||
private Type getValueType(Type collectionType) {
|
||||
private Type valueType(Type collectionType) {
|
||||
return TypeReflectHelper.getValueType(collectionType);
|
||||
}
|
||||
|
||||
@@ -421,7 +384,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
* different jdbcTypes in a single system.
|
||||
*/
|
||||
@Override
|
||||
public ScalarType<?> getScalarType(Class<?> type, int jdbcType) {
|
||||
public ScalarType<?> type(Class<?> type, int jdbcType) {
|
||||
// File is a special Lob so check for that first
|
||||
if (File.class.equals(type)) {
|
||||
return fileType;
|
||||
@@ -430,13 +393,13 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
// check for Clob, LongVarchar etc ...
|
||||
// the reason being that String maps to multiple jdbc types
|
||||
// varchar, clob, longVarchar.
|
||||
ScalarType<?> scalarType = getLobTypes(jdbcType);
|
||||
ScalarType<?> scalarType = lobTypes(jdbcType);
|
||||
if (scalarType != null) {
|
||||
// it is a specific Lob type...
|
||||
return scalarType;
|
||||
}
|
||||
|
||||
scalarType = getScalarType(type);
|
||||
scalarType = type(type);
|
||||
if (scalarType != null) {
|
||||
if (jdbcType == 0 || scalarType.jdbcType() == jdbcType) {
|
||||
// matching type
|
||||
@@ -462,8 +425,8 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
* types - like String - Varchar, LongVarchar, Clob. For this reason I check
|
||||
* for the specific Lob types first before looking for a matching type.
|
||||
*/
|
||||
private ScalarType<?> getLobTypes(int jdbcType) {
|
||||
return getScalarType(jdbcType);
|
||||
private ScalarType<?> lobTypes(int jdbcType) {
|
||||
return type(jdbcType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -507,7 +470,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
* <p>
|
||||
* Return null if the EnumValue annotations are not present/used.
|
||||
*/
|
||||
private ScalarTypeEnum<?> createEnumScalarType2(Class<?> enumType) {
|
||||
private ScalarTypeEnum<?> enumTypeEnumValue(Class<?> enumType) {
|
||||
boolean integerType = true;
|
||||
Map<String, String> nameValueMap = new LinkedHashMap<>();
|
||||
for (Field field : enumType.getDeclaredFields()) {
|
||||
@@ -536,8 +499,8 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
* much shorter codes used in the DB.
|
||||
*/
|
||||
@Override
|
||||
public ScalarType<?> createEnumScalarType(Class<? extends Enum<?>> enumType, EnumType type) {
|
||||
ScalarType<?> scalarType = getScalarType(enumType);
|
||||
public ScalarType<?> enumType(Class<? extends Enum<?>> enumType, EnumType type) {
|
||||
ScalarType<?> scalarType = type(enumType);
|
||||
if (scalarType instanceof ScalarTypeWrapper) {
|
||||
// no override or further mapping required
|
||||
return scalarType;
|
||||
@@ -549,16 +512,16 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
return scalarEnum;
|
||||
}
|
||||
scalarEnum = createEnumScalarTypePerExtentions(enumType);
|
||||
scalarEnum = enumTypePerExtensions(enumType);
|
||||
if (scalarEnum == null) {
|
||||
// use JPA normal Enum type (without mapping)
|
||||
scalarEnum = createEnumScalarTypePerSpec(enumType, type);
|
||||
scalarEnum = enumTypePerSpec(enumType, type);
|
||||
}
|
||||
add(scalarEnum);
|
||||
return scalarEnum;
|
||||
}
|
||||
|
||||
private ScalarTypeEnum<?> createEnumScalarTypePerSpec(Class<?> enumType, EnumType type) {
|
||||
private ScalarTypeEnum<?> enumTypePerSpec(Class<?> enumType, EnumType type) {
|
||||
if (type == null) {
|
||||
if (defaultEnumType == EnumType.ORDINAL) {
|
||||
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
|
||||
@@ -572,16 +535,16 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
}
|
||||
|
||||
private ScalarTypeEnum<?> createEnumScalarTypePerExtentions(Class<? extends Enum<?>> enumType) {
|
||||
private ScalarTypeEnum<?> enumTypePerExtensions(Class<? extends Enum<?>> enumType) {
|
||||
for (Method method : enumType.getMethods()) {
|
||||
DbEnumValue dbValue = AnnotationUtil.get(method, DbEnumValue.class);
|
||||
if (dbValue != null) {
|
||||
boolean integerValues = DbEnumType.INTEGER == dbValue.storage();
|
||||
return createEnumScalarTypeDbValue(enumType, method, integerValues, dbValue.length(), dbValue.withConstraint());
|
||||
return enumTypeDbValue(enumType, method, integerValues, dbValue.length(), dbValue.withConstraint());
|
||||
}
|
||||
}
|
||||
// look for EnumValue annotations instead
|
||||
return createEnumScalarType2(enumType);
|
||||
return enumTypeEnumValue(enumType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -589,7 +552,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
* <p>
|
||||
* Return null if the EnumValue annotations are not present/used.
|
||||
*/
|
||||
private ScalarTypeEnum<?> createEnumScalarTypeDbValue(Class<? extends Enum<?>> enumType, Method method, boolean integerType, int length, boolean withConstraint) {
|
||||
private ScalarTypeEnum<?> enumTypeDbValue(Class<? extends Enum<?>> enumType, Method method, boolean integerType, int length, boolean withConstraint) {
|
||||
Map<String, String> nameValueMap = new LinkedHashMap<>();
|
||||
for (Enum<?> enumConstant : enumType.getEnumConstants()) {
|
||||
try {
|
||||
@@ -671,7 +634,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
Class<?> logicalType = paramTypes[0];
|
||||
Class<?> persistType = paramTypes[1];
|
||||
ScalarType<?> wrappedType = getScalarType(persistType);
|
||||
ScalarType<?> wrappedType = type(persistType);
|
||||
if (wrappedType == null) {
|
||||
throw new IllegalStateException("Could not find ScalarType for: " + paramTypes[1]);
|
||||
}
|
||||
@@ -695,7 +658,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
Class<?> logicalType = paramTypes[0];
|
||||
Class<?> persistType = paramTypes[1];
|
||||
ScalarType<?> wrappedType = getScalarType(persistType);
|
||||
ScalarType<?> wrappedType = type(persistType);
|
||||
if (wrappedType == null) {
|
||||
throw new IllegalStateException("Could not find ScalarType for: " + paramTypes[1]);
|
||||
}
|
||||
@@ -709,29 +672,9 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add support for Jackson's JsonNode mapping to Clob, Blob, Varchar, JSON and JSONB.
|
||||
*/
|
||||
private void initialiseJacksonTypes() {
|
||||
if (objectMapper != null) {
|
||||
ObjectMapper mapper = (ObjectMapper) objectMapper;
|
||||
jsonNodeClob = new ScalarTypeJsonNode.Clob(mapper);
|
||||
jsonNodeBlob = new ScalarTypeJsonNode.Blob(mapper);
|
||||
jsonNodeVarchar = new ScalarTypeJsonNode.Varchar(mapper);
|
||||
jsonNodeJson = jsonNodeClob; // Default for non-Postgres databases
|
||||
jsonNodeJsonb = jsonNodeClob; // Default for non-Postgres databases
|
||||
if (postgres) {
|
||||
jsonNodeJson = new ScalarTypeJsonNodePostgres.JSON(mapper);
|
||||
jsonNodeJsonb = new ScalarTypeJsonNodePostgres.JSONB(mapper);
|
||||
}
|
||||
// add as default mapping for JsonNode (when not annotated with @DbJson etc)
|
||||
typeMap.put(JsonNode.class, jsonNodeJson);
|
||||
}
|
||||
}
|
||||
|
||||
private void initialiseJavaTimeTypes(DatabaseConfig config) {
|
||||
|
||||
ZoneId zoneId = getZoneId(config);
|
||||
ZoneId zoneId = zoneId(config);
|
||||
|
||||
typeMap.put(java.nio.file.Path.class, new ScalarTypePath());
|
||||
addType(java.time.Period.class, new ScalarTypePeriod());
|
||||
@@ -758,7 +701,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
addType(Duration.class, (durationNanos) ? new ScalarTypeDurationWithNanos() : new ScalarTypeDuration());
|
||||
}
|
||||
|
||||
private ZoneId getZoneId(DatabaseConfig config) {
|
||||
private ZoneId zoneId(DatabaseConfig config) {
|
||||
final String dataTimeZone = config.getDataTimeZone();
|
||||
return (dataTimeZone == null) ? ZoneOffset.systemDefault() : TimeZone.getTimeZone(dataTimeZone).toZoneId();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.PostgresHelper;
|
||||
import io.ebean.core.type.ScalarTypeBaseVarchar;
|
||||
import io.ebean.types.Cidr;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.PostgresHelper;
|
||||
import io.ebean.core.type.ScalarTypeBaseVarchar;
|
||||
import io.ebean.types.Inet;
|
||||
|
||||
|
||||
+1
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.PostgresHelper;
|
||||
import io.ebean.core.type.ScalarTypeBaseVarchar;
|
||||
import io.ebean.text.TextException;
|
||||
|
||||
|
||||
@@ -3,10 +3,7 @@ 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.core.type.DataBinder;
|
||||
import io.ebean.core.type.DataReader;
|
||||
import io.ebean.core.type.DocPropertyType;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.core.type.*;
|
||||
import io.ebean.text.TextException;
|
||||
import io.ebean.text.json.EJson;
|
||||
import io.ebeaninternal.json.ModifyAwareList;
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.PostgresHelper;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
|
||||
@@ -3,10 +3,7 @@ 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.core.type.DataBinder;
|
||||
import io.ebean.core.type.DataReader;
|
||||
import io.ebean.core.type.DocPropertyType;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.core.type.*;
|
||||
import io.ebean.text.TextException;
|
||||
import io.ebean.text.json.EJson;
|
||||
import io.ebeaninternal.json.ModifyAwareSet;
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.type;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.PostgresHelper;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.ebean.ModifyAwareType;
|
||||
import io.ebean.annotation.MutationDetection;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.core.type.PostgresHelper;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
|
||||
final class TypeJsonManager {
|
||||
|
||||
@@ -11,47 +11,41 @@ import java.lang.reflect.Type;
|
||||
*/
|
||||
public interface TypeManager {
|
||||
|
||||
/**
|
||||
* Register a ScalarType with the system.
|
||||
*/
|
||||
void add(ScalarType<?> scalarType);
|
||||
|
||||
/**
|
||||
* Return the scalar type for the given logical type.
|
||||
*/
|
||||
ScalarType<?> getScalarType(String cast);
|
||||
ScalarType<?> type(String cast);
|
||||
|
||||
/**
|
||||
* Return the ScalarType for a given jdbc type.
|
||||
*
|
||||
* @param jdbcType as per java.sql.Types
|
||||
*/
|
||||
ScalarType<?> getScalarType(int jdbcType);
|
||||
ScalarType<?> type(int jdbcType);
|
||||
|
||||
/**
|
||||
* Return the ScalarType for a given logical type.
|
||||
*/
|
||||
ScalarType<?> getScalarType(Class<?> type);
|
||||
ScalarType<?> type(Class<?> type);
|
||||
|
||||
/**
|
||||
* For java.util.Date and java.util.Calendar additionally pass the jdbc type
|
||||
* that you would like the ScalarType to map to. This is because these types
|
||||
* can map to different java.sql.Types depending on the property.
|
||||
*/
|
||||
ScalarType<?> getScalarType(Class<?> type, int jdbcType);
|
||||
ScalarType<?> type(Class<?> type, int jdbcType);
|
||||
|
||||
/**
|
||||
* Find and return the ScalarType taking into account the property type with generics.
|
||||
* <p>
|
||||
* For example Array based ScalarType for types like {@code List<String>}.
|
||||
*/
|
||||
ScalarType<?> getScalarType(Type propertyType, Class<?> type);
|
||||
ScalarType<?> type(Type propertyType, Class<?> type);
|
||||
|
||||
/**
|
||||
* Create a ScalarType for an Enum using a mapping (rather than JPA Ordinal
|
||||
* or String which has limitations).
|
||||
* Create a ScalarType for an Enum using a mapping (rather than JPA Ordinal or String which has limitations).
|
||||
*/
|
||||
ScalarType<?> createEnumScalarType(Class<? extends Enum<?>> enumType, EnumType enumerated);
|
||||
ScalarType<?> enumType(Class<? extends Enum<?>> enumType, EnumType enumerated);
|
||||
|
||||
/**
|
||||
* Return the ScalarType used to handle JSON content.
|
||||
@@ -59,20 +53,20 @@ public interface TypeManager {
|
||||
* Note that type expected to be JsonNode or Map.
|
||||
* </p>
|
||||
*/
|
||||
ScalarType<?> getJsonScalarType(DeployBeanProperty prop, int dbType, int dbLength);
|
||||
ScalarType<?> dbJsonType(DeployBeanProperty prop, int dbType, int dbLength);
|
||||
|
||||
/**
|
||||
* Return the ScalarType used to handle DB ARRAY.
|
||||
*/
|
||||
ScalarType<?> getArrayScalarType(Class<?> type, Type genericType, boolean nullable);
|
||||
ScalarType<?> dbArrayType(Class<?> type, Type genericType, boolean nullable);
|
||||
|
||||
/**
|
||||
* Return the ScalarType used to handle HSTORE (Map<String,String>).
|
||||
*/
|
||||
ScalarType<?> getDbMapScalarType();
|
||||
ScalarType<?> dbMapType();
|
||||
|
||||
/**
|
||||
* Return the Geometry type binder if provided.
|
||||
*/
|
||||
GeoTypeBinder getGeoTypeBinder();
|
||||
GeoTypeBinder geoTypeBinder();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ module io.ebean.core {
|
||||
uses io.ebean.config.dbplatform.DatabasePlatformProvider;
|
||||
uses io.ebean.datasource.DataSourceAlertFactory;
|
||||
uses io.ebean.core.type.ExtraTypeFactory;
|
||||
uses io.ebean.core.type.ScalarTypeSetFactory;
|
||||
uses io.ebeanservice.docstore.api.DocStoreFactory;
|
||||
uses io.ebean.migration.auto.AutoMigrationRunner;
|
||||
uses io.avaje.classpath.scanner.ClassPathScannerFactory;
|
||||
|
||||
@@ -46,14 +46,14 @@ public class DefaultTypeManagerTest {
|
||||
public void enumDayMonth_builtIn_overrideAsString() {
|
||||
DefaultTypeManager typeManager = create();
|
||||
|
||||
ScalarType<?> type = typeManager.createEnumScalarType(Month.class, null);
|
||||
ScalarType<?> type = typeManager.enumType(Month.class, null);
|
||||
assertThat(type).isInstanceOf(ScalarTypeEnumWithMapping.class).as("built in type");
|
||||
|
||||
// mapped explicitly as JPA EnumType.STRING
|
||||
type = typeManager.createEnumScalarType(Month.class, EnumType.STRING);
|
||||
type = typeManager.enumType(Month.class, EnumType.STRING);
|
||||
assertThat(type).isInstanceOf(ScalarTypeEnumStandard.StringEnum.class).as("override built in type");
|
||||
try {
|
||||
typeManager.createEnumScalarType(Month.class, EnumType.ORDINAL);
|
||||
typeManager.enumType(Month.class, EnumType.ORDINAL);
|
||||
assertThat(true).isFalse().as("never get here");
|
||||
|
||||
} catch (IllegalStateException e) {
|
||||
@@ -66,10 +66,10 @@ public class DefaultTypeManagerTest {
|
||||
DefaultTypeManager typeManager = create();
|
||||
|
||||
// mapped explicitly as JPA EnumType.STRING
|
||||
ScalarType<?> type = typeManager.createEnumScalarType(Month.class, EnumType.ORDINAL);
|
||||
ScalarType<?> type = typeManager.enumType(Month.class, EnumType.ORDINAL);
|
||||
assertThat(type).isInstanceOf(ScalarTypeEnumStandard.OrdinalEnum.class).as("override built in type");
|
||||
try {
|
||||
typeManager.createEnumScalarType(Month.class, EnumType.STRING);
|
||||
typeManager.enumType(Month.class, EnumType.STRING);
|
||||
assertThat(true).isFalse().as("never get here");
|
||||
} catch (IllegalStateException e) {
|
||||
assertThat(e.getMessage()).contains("It is mapped using 2 different modes when only one is supported");
|
||||
@@ -80,14 +80,14 @@ public class DefaultTypeManagerTest {
|
||||
public void enumDayOfWeek_builtIn_overrideAsString() {
|
||||
DefaultTypeManager typeManager = create();
|
||||
|
||||
ScalarType<?> type = typeManager.createEnumScalarType(DayOfWeek.class, null);
|
||||
ScalarType<?> type = typeManager.enumType(DayOfWeek.class, null);
|
||||
assertThat(type).isInstanceOf(ScalarTypeEnumWithMapping.class).as("built in type");
|
||||
|
||||
// mapped explicitly as JPA EnumType.STRING
|
||||
type = typeManager.createEnumScalarType(DayOfWeek.class, EnumType.STRING);
|
||||
type = typeManager.enumType(DayOfWeek.class, EnumType.STRING);
|
||||
assertThat(type).isInstanceOf(ScalarTypeEnumStandard.StringEnum.class).as("override built in type");
|
||||
try {
|
||||
typeManager.createEnumScalarType(DayOfWeek.class, EnumType.ORDINAL);
|
||||
typeManager.enumType(DayOfWeek.class, EnumType.ORDINAL);
|
||||
assertThat(true).isFalse().as("never get here");
|
||||
} catch (IllegalStateException e) {
|
||||
assertThat(e.getMessage()).contains("It is mapped using 2 different modes when only one is supported");
|
||||
@@ -99,10 +99,10 @@ public class DefaultTypeManagerTest {
|
||||
DefaultTypeManager typeManager = create();
|
||||
|
||||
// mapped explicitly as JPA EnumType.STRING
|
||||
ScalarType<?> type = typeManager.createEnumScalarType(DayOfWeek.class, EnumType.ORDINAL);
|
||||
ScalarType<?> type = typeManager.enumType(DayOfWeek.class, EnumType.ORDINAL);
|
||||
assertThat(type).isInstanceOf(ScalarTypeEnumStandard.OrdinalEnum.class).as("override built in type");
|
||||
try {
|
||||
typeManager.createEnumScalarType(DayOfWeek.class, EnumType.STRING);
|
||||
typeManager.enumType(DayOfWeek.class, EnumType.STRING);
|
||||
assertThat(true).isFalse().as("never get here");
|
||||
} catch (IllegalStateException e) {
|
||||
assertThat(e.getMessage()).contains("It is mapped using 2 different modes when only one is supported");
|
||||
@@ -113,19 +113,19 @@ public class DefaultTypeManagerTest {
|
||||
public void createEnumScalarTypePerExtentions() {
|
||||
DefaultTypeManager typeManager = create();
|
||||
|
||||
ScalarType<?> type = typeManager.createEnumScalarType(VarcharEnum.class, EnumType.ORDINAL);
|
||||
ScalarType<?> type = typeManager.enumType(VarcharEnum.class, EnumType.ORDINAL);
|
||||
assertThat(type).isInstanceOf(ScalarTypeEnumWithMapping.class);
|
||||
// withConstraint false
|
||||
assertThat(((ScalarTypeEnumWithMapping) type).getDbCheckConstraintValues()).isNull();
|
||||
|
||||
type = typeManager.createEnumScalarType(IntEnum.class, EnumType.ORDINAL);
|
||||
type = typeManager.enumType(IntEnum.class, EnumType.ORDINAL);
|
||||
assertThat(type).isInstanceOf(ScalarTypeEnumWithMapping.class);
|
||||
ScalarTypeEnumWithMapping enumWithMapping = (ScalarTypeEnumWithMapping) type;
|
||||
// withConstraint true
|
||||
assertThat(enumWithMapping.getDbCheckConstraintValues()).hasSize(3);
|
||||
assertThat(enumWithMapping.getDbCheckConstraintValues()).contains("100", "101", "102");
|
||||
|
||||
type = typeManager.createEnumScalarType(Car.Size.class, EnumType.ORDINAL);
|
||||
type = typeManager.enumType(Car.Size.class, EnumType.ORDINAL);
|
||||
assertThat(type).isInstanceOf(ScalarTypeEnumWithMapping.class);
|
||||
enumWithMapping = (ScalarTypeEnumWithMapping) type;
|
||||
// withConstraint true
|
||||
|
||||
@@ -31,7 +31,7 @@ class TestTypeManager extends BaseTest {
|
||||
void testEnumWithSubclasses() throws SQLException {
|
||||
DefaultTypeManager typeManager = createTypeManager();
|
||||
|
||||
ScalarType<?> type = typeManager.createEnumScalarType(MyEnum.class, null);
|
||||
ScalarType<?> type = typeManager.enumType(MyEnum.class, null);
|
||||
|
||||
DataReader reader = mock(DataReader.class);
|
||||
when(reader.getString()).thenReturn("A");
|
||||
@@ -44,17 +44,17 @@ class TestTypeManager extends BaseTest {
|
||||
val = type.read(reader);
|
||||
assertThat(val).isEqualTo(MyEnum.Cval);
|
||||
|
||||
ScalarType<?> typeGeneral = typeManager.getScalarType(MyEnum.class);
|
||||
ScalarType<?> typeGeneral = typeManager.type(MyEnum.class);
|
||||
assertThat(typeGeneral).isNotNull();
|
||||
ScalarType<?> typeB = typeManager.getScalarType(MyEnum.Bval.getClass());
|
||||
ScalarType<?> typeB = typeManager.type(MyEnum.Bval.getClass());
|
||||
assertThat(typeB).isNotNull();
|
||||
ScalarType<?> typeA = typeManager.getScalarType(MyEnum.Aval.getClass());
|
||||
ScalarType<?> typeA = typeManager.type(MyEnum.Aval.getClass());
|
||||
assertThat(typeA).isNotNull();
|
||||
ScalarType<?> typeC = typeManager.getScalarType(MyEnum.Cval.getClass());
|
||||
ScalarType<?> typeC = typeManager.type(MyEnum.Cval.getClass());
|
||||
assertThat(typeC).isNotNull();
|
||||
|
||||
try {
|
||||
typeManager.createEnumScalarType(MyEnum.class, EnumType.STRING);
|
||||
typeManager.enumType(MyEnum.class, EnumType.STRING);
|
||||
fail("never get here");
|
||||
} catch (IllegalStateException e) {
|
||||
assertThat(e.getMessage()).contains("It is mapped using 2 different modes when only one is supported");
|
||||
@@ -65,7 +65,7 @@ class TestTypeManager extends BaseTest {
|
||||
void testEnumWithChar() throws SQLException {
|
||||
DefaultTypeManager typeManager = createTypeManager();
|
||||
|
||||
ScalarType<?> dayOfWeekType = typeManager.createEnumScalarType(MyDayOfWeek.class, null);
|
||||
ScalarType<?> dayOfWeekType = typeManager.enumType(MyDayOfWeek.class, null);
|
||||
DataReader reader = mock(DataReader.class);
|
||||
when(reader.getString()).thenReturn("MONDAY ");
|
||||
Object val = dayOfWeekType.read(reader);
|
||||
@@ -88,7 +88,7 @@ class TestTypeManager extends BaseTest {
|
||||
assertThat(val).isEqualTo(MyDayOfWeek.FRIDAY);
|
||||
|
||||
try {
|
||||
typeManager.createEnumScalarType(MyDayOfWeek.class, EnumType.ORDINAL);
|
||||
typeManager.enumType(MyDayOfWeek.class, EnumType.ORDINAL);
|
||||
fail("never get here");
|
||||
} catch (IllegalStateException e) {
|
||||
assertThat(e.getMessage()).contains("It is mapped using 2 different modes when only one is supported");
|
||||
@@ -99,7 +99,7 @@ class TestTypeManager extends BaseTest {
|
||||
void test() {
|
||||
DefaultTypeManager typeManager = createTypeManager();
|
||||
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(Money.class);
|
||||
ScalarType<?> scalarType = typeManager.type(Money.class);
|
||||
assertEquals(Types.DECIMAL, scalarType.jdbcType());
|
||||
assertFalse(scalarType.jdbcNative());
|
||||
assertEquals(Money.class, scalarType.type());
|
||||
@@ -108,15 +108,15 @@ class TestTypeManager extends BaseTest {
|
||||
@Test
|
||||
void testWithConfig() {
|
||||
DefaultTypeManager typeManager1 = createTypeManager();
|
||||
ScalarType<?> type1 = typeManager1.createEnumScalarType(MySex.class, null);
|
||||
ScalarType<?> type1 = typeManager1.enumType(MySex.class, null);
|
||||
assertThat(type1).isInstanceOf(ScalarTypeEnumStandard.OrdinalEnum.class);
|
||||
//
|
||||
DefaultTypeManager typeManager2 = createTypeManagerDefaultEnumTypeString();
|
||||
ScalarType<?> type2 = typeManager2.createEnumScalarType(MySex.class, null);
|
||||
ScalarType<?> type2 = typeManager2.enumType(MySex.class, null);
|
||||
assertThat(type2).isInstanceOf(ScalarTypeEnumStandard.StringEnum.class);
|
||||
//
|
||||
DefaultTypeManager typeManager3 = createTypeManagerDefaultEnumTypeString();
|
||||
ScalarType<?> type3 = typeManager3.createEnumScalarType(MySex.class, EnumType.ORDINAL);
|
||||
ScalarType<?> type3 = typeManager3.enumType(MySex.class, EnumType.ORDINAL);
|
||||
assertThat(type3).isInstanceOf(ScalarTypeEnumStandard.OrdinalEnum.class);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ class TestTypeManager extends BaseTest {
|
||||
@Test
|
||||
void testCalendar() {
|
||||
DefaultTypeManager typeManager = createTypeManager();
|
||||
ScalarType<?> typeB = typeManager.getScalarType(GregorianCalendar.class);
|
||||
ScalarType<?> typeB = typeManager.type(GregorianCalendar.class);
|
||||
assertThat(typeB).isInstanceOf(ScalarTypeCalendar.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.9.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.9.3-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,51 @@
|
||||
package io.ebean.jackson.jsonnode;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.core.type.ScalarTypeSet;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
class JsonNodeSet implements ScalarTypeSet<JsonNode> {
|
||||
|
||||
final ScalarType<JsonNode> varchar;
|
||||
final ScalarType<JsonNode> clob;
|
||||
final ScalarType<JsonNode> blob;
|
||||
final ScalarType<JsonNode> jsonb;
|
||||
final ScalarType<JsonNode> json;
|
||||
|
||||
JsonNodeSet(ScalarType<JsonNode> varchar, ScalarType<JsonNode> clob, ScalarType<JsonNode> blob, ScalarType<JsonNode> jsonb, ScalarType<JsonNode> json) {
|
||||
this.varchar = varchar;
|
||||
this.clob = clob;
|
||||
this.blob = blob;
|
||||
this.jsonb = jsonb;
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> type() {
|
||||
return JsonNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> defaultType() {
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<JsonNode> forType(int dbType) {
|
||||
switch (dbType) {
|
||||
case Types.VARCHAR:
|
||||
return varchar;
|
||||
case Types.BLOB:
|
||||
return blob;
|
||||
case Types.CLOB:
|
||||
return clob;
|
||||
case DbPlatformType.JSONB:
|
||||
return jsonb;
|
||||
default:
|
||||
return json;
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package io.ebean.jackson.jsonnode;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.core.type.PostgresHelper;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.core.type.ScalarTypeSet;
|
||||
import io.ebean.core.type.ScalarTypeSetFactory;
|
||||
|
||||
public class JsonNodeTypeFactory implements ScalarTypeSetFactory {
|
||||
|
||||
@Override
|
||||
public ScalarTypeSet<?> createTypeSet(DatabaseConfig config, Object objectMapper) {
|
||||
if (objectMapper == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ObjectMapper mapper = (ObjectMapper) objectMapper;
|
||||
var varchar = new ScalarTypeJsonNode.Varchar(mapper);
|
||||
var clob = new ScalarTypeJsonNode.Clob(mapper);
|
||||
var blob = new ScalarTypeJsonNode.Blob(mapper);
|
||||
ScalarType<JsonNode> json = clob; // Default for non-Postgres databases
|
||||
ScalarType<JsonNode> jsonb = clob; // Default for non-Postgres databases
|
||||
if (PostgresHelper.isPostgresCompatible(config.getDatabasePlatform())) {
|
||||
json = new ScalarTypeJsonNodePostgres.JSON(mapper);
|
||||
jsonb = new ScalarTypeJsonNodePostgres.JSONB(mapper);
|
||||
}
|
||||
return new JsonNodeSet(varchar, clob, blob, jsonb, json);
|
||||
}
|
||||
}
|
||||
+4
-7
@@ -1,4 +1,4 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
package io.ebean.jackson.jsonnode;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
@@ -11,11 +11,7 @@ import io.ebean.core.type.ScalarTypeBase;
|
||||
import io.ebean.text.TextException;
|
||||
import io.ebean.util.IOUtils;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
@@ -182,7 +178,8 @@ abstract class ScalarTypeJsonNode extends ScalarTypeBase<JsonNode> {
|
||||
if (value == null) {
|
||||
dataOutput.writeBoolean(false);
|
||||
} else {
|
||||
ScalarHelp.writeUTF(dataOutput, format(value));
|
||||
dataOutput.writeBoolean(true);
|
||||
dataOutput.writeUTF(format(value));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,9 +1,10 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
package io.ebean.jackson.jsonnode;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.PostgresHelper;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import io.ebean.jackson.jsonnode.JsonNodeTypeFactory;
|
||||
|
||||
module io.ebean.jackson.jsonnode {
|
||||
|
||||
requires io.ebean.core.type;
|
||||
requires com.fasterxml.jackson.core;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
|
||||
provides io.ebean.core.type.ScalarTypeSetFactory with JsonNodeTypeFactory;
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
io.ebean.jackson.jsonnode.JsonNodeTypeFactory
|
||||
@@ -109,6 +109,13 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.9.3-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
|
||||
Reference in New Issue
Block a user