Skip to content

Commit

Permalink
Preliminary work for #628 (mapping JSON types with Hibernate 6's nati…
Browse files Browse the repository at this point in the history
…ve JSON mapping)
  • Loading branch information
alessiostalla committed Dec 24, 2022
1 parent 949a9a0 commit 4c2d76e
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 180 deletions.
19 changes: 0 additions & 19 deletions databases/postgresql/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,6 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.marvinformatics.hibernate</groupId>
<artifactId>hibernate-native-json</artifactId>
<version>0.5</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<resources>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.hibernate.dialect.PostgreSQL82Dialect;
import org.hibernate.usertype.DynamicParameterizedType;

import java.math.BigDecimal;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.List;
Expand All @@ -46,7 +47,7 @@ public class PostgreSQLDatabasePlatform extends AbstractDatabasePlatform {
public final static String DESCRIPTION = "PostgreSQL";
public final static String STANDARD_DRIVER_CLASS_NAME =
"org.postgresql.Driver";

//**************************************************************************
// Constructors
//**************************************************************************
Expand Down Expand Up @@ -74,6 +75,7 @@ public boolean isApplicable(ConnectionProvider connectionProvider) {
@Override
public TypeDescriptor getDatabaseSpecificType(Column column) {
if ("JSONB".equalsIgnoreCase(column.getColumnType())) {
// TODO Hibernate 6 should support JSON mapping na
Properties typeParams = new Properties();
if(column.getActualJavaType() == Map.class) {
typeParams.put(DynamicParameterizedType.PARAMETER_TYPE, new ColumnParameterType(column, Map.class));
Expand All @@ -94,4 +96,12 @@ public List<String[]> getSchemaNames(DatabaseMetaData databaseMetaData) throws S
schemaNames.removeIf(schema -> "information_schema".equalsIgnoreCase(schema[1]) || schema[1].startsWith("pg_"));
return schemaNames;
}

@Override
protected Class<? extends Number> getDefaultNumericType(Integer precision) {
if(precision != null && precision == 131089) {
return BigDecimal.class; //Postgres bug - #925
}
return super.getDefaultNumericType(precision);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.manydesigns.portofino.database.platforms;

import com.manydesigns.portofino.database.model.Type;
import com.manydesigns.portofino.database.model.platforms.TypeProvider;
import org.jetbrains.annotations.Nullable;

import java.sql.Types;
import java.util.List;
import java.util.Map;

public class PostgreSQLTypeProvider implements TypeProvider {
@Nullable
@Override
public Class<?> getDefaultJavaType(int jdbcType, String typeName, Integer precision, Integer scale) {
if (jdbcType == Types.OTHER && "JSONB".equalsIgnoreCase(typeName)) {
return String.class;
} else {
return null;
}
}

@Override
public Class[] getAvailableJavaTypes(Type type, Integer length) {
if("JSONB".equalsIgnoreCase(type.getTypeName())) {
return new Class[] { String.class, Map.class, List.class };
} else {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package com.manydesigns.portofino.database.model;

import com.manydesigns.elements.annotations.Required;
import com.manydesigns.portofino.database.model.platforms.DatabasePlatform;
import com.manydesigns.portofino.model.*;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -264,7 +265,9 @@ public Class<?> getActualJavaType() {
if (property.getEType() != null) {
return property.getEType().getInstanceClass();
} else {
return Type.getDefaultJavaType(getJdbcType(), getColumnType(), getLength(), getScale());
DatabasePlatform databasePlatform =
getTable().getSchema().getDatabase().getConnectionProvider().getDatabasePlatform();
return databasePlatform.getDefaultJavaType(getJdbcType(), getColumnType(), getLength(), getScale());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2020 ManyDesigns srl. All rights reserved.
* Copyright (C) 2005-2022 ManyDesigns srl. All rights reserved.
* http://www.manydesigns.com/
*
* This is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -37,27 +37,23 @@
import java.util.List;
import java.util.Map;

/*
* @author Paolo Predonzani - [email protected]
* @author Angelo Lupo - [email protected]
* @author Giampiero Granatella - [email protected]
* @author Alessio Stalla - [email protected]
/**
* Represents all known information about a data type in a database.
* @author Paolo Predonzani - [email protected]
* @author Angelo Lupo - [email protected]
* @author Giampiero Granatella - [email protected]
* @author Alessio Stalla - [email protected]
*/
public class Type {
public static final String copyright =
"Copyright (C) 2005-2020 ManyDesigns srl";

//**************************************************************************
// Logger
//**************************************************************************
"Copyright (C) 2005-2022 ManyDesigns srl";

public final static Logger logger = LoggerFactory.getLogger(Type.class);

//**************************************************************************
// Fields
//**************************************************************************

protected final String typeName;
/**
* The JDBC type number, as returned by the JDBC driver.
*/
protected final int jdbcType;
protected final boolean autoincrement;
protected final Integer maximumPrecision;
Expand All @@ -71,11 +67,6 @@ public class Type {
protected final Boolean precisionRequired;
protected final Boolean scaleRequired;


//**************************************************************************
// Constructors
//**************************************************************************

public Type(String typeName, int jdbcType, Integer maximumPrecision,
String literalPrefix, String literalSuffix,
boolean nullable, boolean caseSensitive, boolean searchable,
Expand Down Expand Up @@ -131,125 +122,6 @@ public int getJdbcType() {
return jdbcType;
}

public Class getDefaultJavaType() {
return getDefaultJavaType(jdbcType, typeName, maximumPrecision, maximumScale);
}

public static @Nullable Class getDefaultJavaType(int jdbcType, String databaseType, Integer precision, Integer scale) {
switch (jdbcType) {
case Types.BIGINT:
return Long.class;
case Types.BIT:
case Types.BOOLEAN:
return Boolean.class;
case Types.CHAR:
case Types.VARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
case Types.CLOB:
case Types.LONGVARCHAR:
return String.class;
case Types.DATE:
return java.sql.Date.class;
case Types.TIME:
return Time.class;
case Types.TIMESTAMP:
return Timestamp.class;
case Types.DECIMAL:
case Types.NUMERIC:
if(scale != null && scale > 0) {
return BigDecimal.class;
} else {
return getDefaultIntegerType(precision);
}
case Types.DOUBLE:
case Types.REAL:
return Double.class;
case Types.FLOAT:
return Float.class;
case Types.INTEGER:
return getDefaultIntegerType(precision);
case Types.SMALLINT:
return Short.class;
case Types.TINYINT:
return Byte.class;
case Types.BINARY:
case Types.BLOB:
case Types.LONGVARBINARY:
case Types.VARBINARY:
return byte[].class;
case Types.ARRAY:
return java.sql.Array.class;
case Types.DATALINK:
return java.net.URL.class;
case Types.DISTINCT:
case Types.JAVA_OBJECT:
return Object.class;
case Types.NULL:
case Types.REF:
return java.sql.Ref.class;
case Types.OTHER:
if("JSONB".equalsIgnoreCase(databaseType)) { //TODO make configurable by modules
return String.class;
} else {
return java.sql.Ref.class;
}
case Types.STRUCT:
return java.sql.Struct.class;
default:
logger.warn("Unsupported jdbc type: {}", jdbcType);
return null;
}
}

public static Class<? extends Number> getDefaultIntegerType(Integer precision) {
if(precision == null) {
return BigInteger.class;
}
if(precision < Math.log10(Integer.MAX_VALUE)) {
return Integer.class;
} else if(precision < Math.log10(Long.MAX_VALUE)) {
return Long.class;
} else {
if(precision == 131089) {
return BigDecimal.class; //Postgres bug - #925
} else {
return BigInteger.class;
}
}
}

public Class[] getAvailableJavaTypes(Integer length) {
if(isNumeric()) {
return new Class[] {
Integer.class, Long.class, Byte.class, Short.class,
Float.class, Double.class, BigInteger.class, BigDecimal.class,
Boolean.class };
} else {
if("JSONB".equalsIgnoreCase(typeName)) { //TODO make configurable by modules
return new Class[] { String.class, Map.class, List.class };
}
Class defaultJavaType = getDefaultJavaType();
if(defaultJavaType == String.class) {
if(length != null && length < 256) {
return new Class[] { String.class, Boolean.class };
} else {
return new Class[] { String.class };
}
} else if(defaultJavaType == Timestamp.class) {
return new Class[] { Timestamp.class, DateTime.class, java.sql.Date.class, LocalDateTime.class, ZonedDateTime.class, Instant.class };
} else if(defaultJavaType == java.sql.Date.class) {
return new Class[] { java.sql.Date.class, DateTime.class, LocalDate.class, Timestamp.class }; //TODO Joda LocalDate as well?
} else {
if(defaultJavaType != null) {
return new Class[] { defaultJavaType };
} else {
return new Class[] { Object.class };
}
}
}
}

public boolean isAutoincrement() {
return autoincrement;
}
Expand Down
Loading

0 comments on commit 4c2d76e

Please sign in to comment.