HHH-15748 Use JSON DDL type on Oracle 21+ and BLOB on 12+
This commit is contained in:
parent
5b5721f64b
commit
276b7a6f95
|
@ -463,6 +463,8 @@ alter database drop logfile group 1;
|
|||
alter database drop logfile group 2;
|
||||
alter database drop logfile group 3;
|
||||
alter system set open_cursors=1000 sid='*' scope=both;
|
||||
create user hibernate_orm_test identified by hibernate_orm_test quota unlimited on users;
|
||||
grant all privileges to hibernate_orm_test;
|
||||
EOF\""
|
||||
}
|
||||
|
||||
|
@ -502,6 +504,8 @@ alter system set open_cursors=1000 sid='*' scope=both;
|
|||
alter system set processes=150 scope=spfile;
|
||||
alter system set filesystemio_options=asynch scope=spfile;
|
||||
alter system set disk_asynch_io=true scope=spfile;
|
||||
create user hibernate_orm_test identified by hibernate_orm_test quota unlimited on users;
|
||||
grant all privileges to hibernate_orm_test;
|
||||
EOF\""
|
||||
echo "Waiting for Oracle to restart after configuration..."
|
||||
$CONTAINER_CLI stop oracle
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.userguide.mapping.basic;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -107,13 +110,33 @@ public abstract class JsonMappingTests {
|
|||
assertThat( entityWithJson.objectMap, is( objectMap ) );
|
||||
assertThat( entityWithJson.list, is( list ) );
|
||||
assertThat( entityWithJson.jsonString, isOneOf( json, alternativeJson ) );
|
||||
String nativeJson = session.createNativeQuery(
|
||||
Object nativeJson = session.createNativeQuery(
|
||||
"select jsonString from EntityWithJson",
|
||||
String.class
|
||||
Object.class
|
||||
)
|
||||
.getResultList()
|
||||
.get( 0 );
|
||||
assertThat( nativeJson, isOneOf( json, alternativeJson ) );
|
||||
final String jsonText;
|
||||
try {
|
||||
if ( nativeJson instanceof Blob ) {
|
||||
final Blob blob = (Blob) nativeJson;
|
||||
jsonText = new String(
|
||||
blob.getBytes( 1L, (int) blob.length() ),
|
||||
StandardCharsets.UTF_8
|
||||
);
|
||||
}
|
||||
else if ( nativeJson instanceof Clob ) {
|
||||
final Clob jsonClob = (Clob) nativeJson;
|
||||
jsonText = jsonClob.getSubString( 1L, (int) jsonClob.length() );
|
||||
}
|
||||
else {
|
||||
jsonText = (String) nativeJson;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
assertThat( jsonText, isOneOf( json, alternativeJson ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -131,8 +131,8 @@ ext {
|
|||
oracle_ci : [
|
||||
'db.dialect' : 'org.hibernate.dialect.OracleDialect',
|
||||
'jdbc.driver': 'oracle.jdbc.OracleDriver',
|
||||
'jdbc.user' : 'SYSTEM',
|
||||
'jdbc.pass' : 'Oracle18',
|
||||
'jdbc.user' : 'hibernate_orm_test',
|
||||
'jdbc.pass' : 'hibernate_orm_test',
|
||||
'jdbc.url' : 'jdbc:oracle:thin:@' + dbHost + ':1521:XE',
|
||||
'connection.init_sql' : ''
|
||||
],
|
||||
|
|
|
@ -62,6 +62,8 @@ dependencies {
|
|||
implementation libs.logging
|
||||
|
||||
compileOnly libs.loggingAnnotations
|
||||
// Used for compiling some Oracle specific JdbcTypes
|
||||
compileOnly dbLibs.oracle
|
||||
|
||||
// JUnit dependencies made up of:
|
||||
// * JUnit 5
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.dialect.BooleanDecoder;
|
|||
import org.hibernate.dialect.DatabaseVersion;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.OracleArrayJdbcType;
|
||||
import org.hibernate.dialect.OracleTypes;
|
||||
import org.hibernate.dialect.OracleTypesHelper;
|
||||
import org.hibernate.dialect.OracleXmlJdbcType;
|
||||
import org.hibernate.dialect.Replacer;
|
||||
|
@ -85,6 +86,7 @@ import org.hibernate.type.StandardBasicTypes;
|
|||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JsonBlobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.NullJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectNullAsNullTypeJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
@ -109,6 +111,7 @@ import static org.hibernate.type.SqlTypes.DATE;
|
|||
import static org.hibernate.type.SqlTypes.DECIMAL;
|
||||
import static org.hibernate.type.SqlTypes.GEOMETRY;
|
||||
import static org.hibernate.type.SqlTypes.INTEGER;
|
||||
import static org.hibernate.type.SqlTypes.JSON;
|
||||
import static org.hibernate.type.SqlTypes.NUMERIC;
|
||||
import static org.hibernate.type.SqlTypes.NVARCHAR;
|
||||
import static org.hibernate.type.SqlTypes.REAL;
|
||||
|
@ -632,6 +635,12 @@ public class OracleLegacyDialect extends Dialect {
|
|||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( SQLXML, "SYS.XMLTYPE", this ) );
|
||||
if ( getVersion().isSameOrAfter( 10 ) ) {
|
||||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "MDSYS.SDO_GEOMETRY", this ) );
|
||||
if ( getVersion().isSameOrAfter( 21 ) ) {
|
||||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "json", this ) );
|
||||
}
|
||||
else if ( getVersion().isSameOrAfter( 12 ) ) {
|
||||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "blob", this ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -669,6 +678,8 @@ public class OracleLegacyDialect extends Dialect {
|
|||
int scale,
|
||||
JdbcTypeRegistry jdbcTypeRegistry) {
|
||||
switch ( jdbcTypeCode ) {
|
||||
case OracleTypes.JSON:
|
||||
return jdbcTypeRegistry.getDescriptor( JSON );
|
||||
case Types.NUMERIC:
|
||||
if ( scale == -127 ) {
|
||||
// For some reason, the Oracle JDBC driver reports FLOAT
|
||||
|
@ -744,6 +755,13 @@ public class OracleLegacyDialect extends Dialect {
|
|||
BlobJdbcType.DEFAULT;
|
||||
|
||||
typeContributions.contributeJdbcType( descriptor );
|
||||
|
||||
if ( getVersion().isSameOrAfter( 21 ) ) {
|
||||
typeContributions.contributeJdbcType( OracleTypesHelper.INSTANCE.getJsonJdbcType() );
|
||||
}
|
||||
else {
|
||||
typeContributions.contributeJdbcType( JsonBlobJdbcType.INSTANCE );
|
||||
}
|
||||
}
|
||||
|
||||
typeContributions.contributeJdbcType( OracleArrayJdbcType.INSTANCE );
|
||||
|
|
|
@ -74,6 +74,7 @@ import org.hibernate.type.StandardBasicTypes;
|
|||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JsonBlobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.NullJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectNullAsNullTypeJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
@ -608,6 +609,12 @@ public class OracleDialect extends Dialect {
|
|||
|
||||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( SQLXML, "SYS.XMLTYPE", this ) );
|
||||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( GEOMETRY, "MDSYS.SDO_GEOMETRY", this ) );
|
||||
if ( getVersion().isSameOrAfter( 21 ) ) {
|
||||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "json", this ) );
|
||||
}
|
||||
else if ( getVersion().isSameOrAfter( 12 ) ) {
|
||||
ddlTypeRegistry.addDescriptor( new DdlTypeImpl( JSON, "blob", this ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -643,6 +650,8 @@ public class OracleDialect extends Dialect {
|
|||
int scale,
|
||||
JdbcTypeRegistry jdbcTypeRegistry) {
|
||||
switch ( jdbcTypeCode ) {
|
||||
case OracleTypes.JSON:
|
||||
return jdbcTypeRegistry.getDescriptor( JSON );
|
||||
case Types.NUMERIC:
|
||||
if ( scale == -127 ) {
|
||||
// For some reason, the Oracle JDBC driver reports FLOAT
|
||||
|
@ -718,6 +727,13 @@ public class OracleDialect extends Dialect {
|
|||
BlobJdbcType.DEFAULT;
|
||||
|
||||
typeContributions.contributeJdbcType( descriptor );
|
||||
|
||||
if ( getVersion().isSameOrAfter( 21 ) ) {
|
||||
typeContributions.contributeJdbcType( OracleTypesHelper.INSTANCE.getJsonJdbcType() );
|
||||
}
|
||||
else {
|
||||
typeContributions.contributeJdbcType( JsonBlobJdbcType.INSTANCE );
|
||||
}
|
||||
}
|
||||
|
||||
typeContributions.contributeJdbcType( OracleArrayJdbcType.INSTANCE );
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
||||
import oracle.jdbc.OracleType;
|
||||
|
||||
/**
|
||||
* Specialized type mapping for {@code JSON} that encodes as OSON.
|
||||
* This class is used from {@link OracleTypesHelper} reflectively to avoid loading Oracle JDBC classes eagerly.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class OracleJsonJdbcType implements JdbcType {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final OracleJsonJdbcType INSTANCE = new OracleJsonJdbcType();
|
||||
|
||||
private static final int JSON_TYPE_CODE = OracleType.JSON.getVendorTypeNumber();
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return SqlTypes.BLOB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultSqlTypeCode() {
|
||||
return SqlTypes.JSON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OracleJsonJdbcType";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
|
||||
// No literal support for now
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
final String json = options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().toString(
|
||||
value,
|
||||
getJavaType(),
|
||||
options
|
||||
);
|
||||
st.setObject( index, json, JSON_TYPE_CODE );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
final String json = options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().toString(
|
||||
value,
|
||||
getJavaType(),
|
||||
options
|
||||
);
|
||||
st.setObject( name, json, JSON_TYPE_CODE );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return getObject( rs.getString( paramIndex ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return getObject( statement.getString( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return getObject( statement.getString( name ), options );
|
||||
}
|
||||
|
||||
private X getObject(String json, WrapperOptions options) throws SQLException {
|
||||
if ( json == null ) {
|
||||
return null;
|
||||
}
|
||||
return options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().fromString(
|
||||
json,
|
||||
getJavaType(),
|
||||
options
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
/**
|
||||
* The Oracle specific JDBC type code.
|
||||
*/
|
||||
public class OracleTypes {
|
||||
public static final int JSON = 2016;
|
||||
}
|
|
@ -9,6 +9,8 @@ package org.hibernate.dialect;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JsonJdbcType;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -27,8 +29,10 @@ public class OracleTypesHelper {
|
|||
|
||||
private static final String ORACLE_TYPES_CLASS_NAME = "oracle.jdbc.OracleTypes";
|
||||
private static final String DEPRECATED_ORACLE_TYPES_CLASS_NAME = "oracle.jdbc.driver.OracleTypes";
|
||||
private static final String ORACLE_JSON_JDBC_TYPE_CLASS_NAME = "org.hibernate.dialect.OracleJsonJdbcType";
|
||||
|
||||
private final int oracleCursorTypeSqlType;
|
||||
private final JdbcType jsonJdbcType;
|
||||
|
||||
private OracleTypesHelper() {
|
||||
int typeCode = -99;
|
||||
|
@ -39,6 +43,17 @@ public class OracleTypesHelper {
|
|||
log.warn( "Unable to resolve Oracle CURSOR JDBC type code: the class OracleTypesHelper was initialized but the Oracle JDBC driver could not be loaded." );
|
||||
}
|
||||
oracleCursorTypeSqlType = typeCode;
|
||||
|
||||
JdbcType jsonJdbcType = JsonJdbcType.INSTANCE;
|
||||
try {
|
||||
jsonJdbcType = (JdbcType) ReflectHelper.classForName( ORACLE_JSON_JDBC_TYPE_CLASS_NAME )
|
||||
.getField( "INSTANCE" )
|
||||
.get( null );
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.warn( "Unable to resolve OracleJsonJdbcType: the class OracleTypesHelper was initialized but the Oracle JDBC driver could not be loaded." );
|
||||
}
|
||||
this.jsonJdbcType = jsonJdbcType;
|
||||
}
|
||||
|
||||
private int extractOracleCursorTypeValue() {
|
||||
|
@ -75,6 +90,10 @@ public class OracleTypesHelper {
|
|||
return oracleCursorTypeSqlType;
|
||||
}
|
||||
|
||||
public JdbcType getJsonJdbcType() {
|
||||
return jsonJdbcType;
|
||||
}
|
||||
|
||||
// initial code as copied from Oracle8iDialect
|
||||
//
|
||||
// private int oracleCursorTypeSqlType = INIT_ORACLETYPES_CURSOR_VALUE;
|
||||
|
|
|
@ -820,7 +820,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
else if ( getFactory().getMappingMetamodel().isEntityClass(resultClass) ) {
|
||||
query.addEntity( "alias1", resultClass.getName(), LockMode.READ );
|
||||
}
|
||||
else {
|
||||
else if ( resultClass != Object.class && resultClass != Object[].class ) {
|
||||
query.addScalar( 1, resultClass );
|
||||
}
|
||||
return query;
|
||||
|
|
|
@ -191,6 +191,7 @@ public class JdbcTypeJavaClassMappings {
|
|||
workMap.put( SqlTypes.ROWID, RowId.class );
|
||||
workMap.put( SqlTypes.SQLXML, SQLXML.class );
|
||||
workMap.put( SqlTypes.UUID, UUID.class );
|
||||
workMap.put( SqlTypes.JSON, String.class );
|
||||
workMap.put( SqlTypes.INET, InetAddress.class );
|
||||
workMap.put( SqlTypes.TIMESTAMP_UTC, Instant.class );
|
||||
workMap.put( SqlTypes.INTERVAL_SECOND, Duration.class );
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.type.descriptor.jdbc;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
* Specialized type mapping for {@code JSON} and the BLOB SQL data type.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class JsonBlobJdbcType implements JdbcType {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final JsonBlobJdbcType INSTANCE = new JsonBlobJdbcType();
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return SqlTypes.BLOB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultSqlTypeCode() {
|
||||
return SqlTypes.JSON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JsonBlobJdbcType";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
|
||||
// No literal support for now
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
final String json = options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().toString(
|
||||
value,
|
||||
getJavaType(),
|
||||
options
|
||||
);
|
||||
st.setBytes( index, json.getBytes( StandardCharsets.UTF_8 ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
final String json = options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().toString(
|
||||
value,
|
||||
getJavaType(),
|
||||
options
|
||||
);
|
||||
st.setBytes( name, json.getBytes( StandardCharsets.UTF_8 ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return getObject( rs.getBytes( paramIndex ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return getObject( statement.getBytes( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return getObject( statement.getBytes( name ), options );
|
||||
}
|
||||
|
||||
private X getObject(byte[] json, WrapperOptions options) throws SQLException {
|
||||
if ( json == null ) {
|
||||
return null;
|
||||
}
|
||||
return options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().fromString(
|
||||
new String( json, StandardCharsets.UTF_8 ),
|
||||
getJavaType(),
|
||||
options
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ public final class JacksonJsonFormatMapper implements FormatMapper {
|
|||
|
||||
@Override
|
||||
public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
|
||||
if ( javaType.getJavaType() == String.class ) {
|
||||
if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
|
||||
return (T) charSequence.toString();
|
||||
}
|
||||
try {
|
||||
|
@ -45,7 +45,7 @@ public final class JacksonJsonFormatMapper implements FormatMapper {
|
|||
|
||||
@Override
|
||||
public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
|
||||
if ( javaType.getJavaType() == String.class ) {
|
||||
if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
|
||||
return (String) value;
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -33,7 +33,7 @@ public final class JacksonXmlFormatMapper implements FormatMapper {
|
|||
|
||||
@Override
|
||||
public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
|
||||
if ( javaType.getJavaType() == String.class ) {
|
||||
if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
|
||||
return (T) charSequence.toString();
|
||||
}
|
||||
try {
|
||||
|
@ -46,7 +46,7 @@ public final class JacksonXmlFormatMapper implements FormatMapper {
|
|||
|
||||
@Override
|
||||
public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
|
||||
if ( javaType.getJavaType() == String.class ) {
|
||||
if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
|
||||
return (String) value;
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -33,7 +33,7 @@ public final class JsonBJsonFormatMapper implements FormatMapper {
|
|||
|
||||
@Override
|
||||
public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
|
||||
if ( javaType.getJavaType() == String.class ) {
|
||||
if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
|
||||
return (T) charSequence.toString();
|
||||
}
|
||||
try {
|
||||
|
@ -46,7 +46,7 @@ public final class JsonBJsonFormatMapper implements FormatMapper {
|
|||
|
||||
@Override
|
||||
public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
|
||||
if ( javaType.getJavaType() == String.class ) {
|
||||
if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
|
||||
return (String) value;
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -51,7 +51,7 @@ public final class JaxbXmlFormatMapper implements FormatMapper {
|
|||
|
||||
@Override
|
||||
public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
|
||||
if ( javaType.getJavaType() == String.class ) {
|
||||
if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
|
||||
return (T) charSequence.toString();
|
||||
}
|
||||
try {
|
||||
|
@ -194,7 +194,7 @@ public final class JaxbXmlFormatMapper implements FormatMapper {
|
|||
|
||||
@Override
|
||||
public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
|
||||
if ( javaType.getJavaType() == String.class ) {
|
||||
if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
|
||||
return (String) value;
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -16,7 +16,7 @@ earlier versions, see any other pertinent migration guides as well.
|
|||
|
||||
=== UUID mapping changes on MariaDB
|
||||
|
||||
On MariaDB, the type code `SqlType.UUID` now by default refers to the DDL type `uuid`, whereas before it was using `binary(16)`.
|
||||
On MariaDB, the type code `SqlTypes.UUID` now by default refers to the DDL type `uuid`, whereas before it was using `binary(16)`.
|
||||
Due to this change, schema validation errors could occur on existing databases.
|
||||
|
||||
The migration to `uuid` requires a migration expression like `cast(old as uuid)`.
|
||||
|
@ -25,13 +25,24 @@ To retain backwards compatibility, configure the setting `hibernate.type.preferr
|
|||
|
||||
=== UUID mapping changes on SQL Server
|
||||
|
||||
On SQL Server, the type code `SqlType.UUID` now by default refers to the DDL type `uniqueidentifier`, whereas before it was using `binary(16)`.
|
||||
On SQL Server, the type code `SqlTypes.UUID` now by default refers to the DDL type `uniqueidentifier`, whereas before it was using `binary(16)`.
|
||||
Due to this change, schema validation errors could occur on existing databases.
|
||||
|
||||
The migration to `uuid` requires a migration expression like `cast(old as uuid)`.
|
||||
|
||||
To retain backwards compatibility, configure the setting `hibernate.type.preferred_uuid_jdbc_type` to `BINARY`.
|
||||
|
||||
=== JSON mapping changes on Oracle
|
||||
|
||||
On Oracle 12.1+, the type code `SqlTypes.JSON` now by default refers to the DDL type `blob` and on 21+ to `json`, whereas before it was using `clob`.
|
||||
Due to this change, schema validation errors could occur on existing databases.
|
||||
|
||||
The migration to `blob` and `json` requires a migration expression like `cast(old as blob)` and `cast(old as json)` respectively.
|
||||
|
||||
To get the old behavior, annotate the column with `@Column(definition = "clob")`.
|
||||
|
||||
This change was done because `blob` and `json` are way more efficient and because we don't expect wide usage of `SqlTypes.JSON` yet.
|
||||
|
||||
=== Column type inference for `number(n,0)` in native SQL queries on Oracle
|
||||
|
||||
Previously, since Hibernate 6.0, columns of type `number` with scale 0 on Oracle were interpreted as `boolean`, `tinyint`, `smallint`, `int`, or `bigint`,
|
||||
|
|
Loading…
Reference in New Issue