HHH-16224 Refactor discovery of exact JDBC drivers, avoid static state in specialized types
This commit is contained in:
parent
02b7c5afb5
commit
8d93c0ca33
|
@ -30,15 +30,11 @@ import org.hibernate.boot.model.TypeContributions;
|
||||||
import org.hibernate.dialect.DatabaseVersion;
|
import org.hibernate.dialect.DatabaseVersion;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.NationalizationSupport;
|
import org.hibernate.dialect.NationalizationSupport;
|
||||||
|
import org.hibernate.dialect.PgJdbcHelper;
|
||||||
import org.hibernate.dialect.PostgreSQLCastingInetJdbcType;
|
import org.hibernate.dialect.PostgreSQLCastingInetJdbcType;
|
||||||
import org.hibernate.dialect.PostgreSQLCastingIntervalSecondJdbcType;
|
import org.hibernate.dialect.PostgreSQLCastingIntervalSecondJdbcType;
|
||||||
import org.hibernate.dialect.PostgreSQLCastingJsonJdbcType;
|
import org.hibernate.dialect.PostgreSQLCastingJsonJdbcType;
|
||||||
import org.hibernate.dialect.PostgreSQLDriverKind;
|
import org.hibernate.dialect.PostgreSQLDriverKind;
|
||||||
import org.hibernate.dialect.PostgreSQLInetJdbcType;
|
|
||||||
import org.hibernate.dialect.PostgreSQLIntervalSecondJdbcType;
|
|
||||||
import org.hibernate.dialect.PostgreSQLJsonJdbcType;
|
|
||||||
import org.hibernate.dialect.PostgreSQLJsonbJdbcType;
|
|
||||||
import org.hibernate.dialect.PostgreSQLPGObjectJdbcType;
|
|
||||||
import org.hibernate.dialect.RowLockStrategy;
|
import org.hibernate.dialect.RowLockStrategy;
|
||||||
import org.hibernate.dialect.SimpleDatabaseVersion;
|
import org.hibernate.dialect.SimpleDatabaseVersion;
|
||||||
import org.hibernate.dialect.SpannerDialect;
|
import org.hibernate.dialect.SpannerDialect;
|
||||||
|
@ -331,15 +327,15 @@ public class CockroachLegacyDialect extends Dialect {
|
||||||
jdbcTypeRegistry.addDescriptor( TIMESTAMP_UTC, InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptor( TIMESTAMP_UTC, InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
||||||
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||||
if ( PostgreSQLPGObjectJdbcType.isUsable() ) {
|
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLIntervalSecondJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getIntervalJdbcType( serviceRegistry ) );
|
||||||
|
|
||||||
if ( getVersion().isSameOrAfter( 20, 0 ) ) {
|
if ( getVersion().isSameOrAfter( 20, 0 ) ) {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLInetJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getInetJdbcType( serviceRegistry ) );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLJsonbJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getJsonbJdbcType( serviceRegistry ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLJsonJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getJsonJdbcType( serviceRegistry ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -23,12 +23,11 @@ import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.BooleanDecoder;
|
import org.hibernate.dialect.BooleanDecoder;
|
||||||
import org.hibernate.dialect.DatabaseVersion;
|
import org.hibernate.dialect.DatabaseVersion;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.OracleArrayJdbcType;
|
|
||||||
import org.hibernate.dialect.OracleBooleanJdbcType;
|
import org.hibernate.dialect.OracleBooleanJdbcType;
|
||||||
|
import org.hibernate.dialect.OracleJdbcHelper;
|
||||||
import org.hibernate.dialect.OracleJsonJdbcType;
|
import org.hibernate.dialect.OracleJsonJdbcType;
|
||||||
|
import org.hibernate.dialect.OracleReflectionStructJdbcType;
|
||||||
import org.hibernate.dialect.OracleTypes;
|
import org.hibernate.dialect.OracleTypes;
|
||||||
import org.hibernate.dialect.OracleStructJdbcType;
|
|
||||||
import org.hibernate.dialect.OracleTypesHelper;
|
|
||||||
import org.hibernate.dialect.OracleXmlJdbcType;
|
import org.hibernate.dialect.OracleXmlJdbcType;
|
||||||
import org.hibernate.dialect.Replacer;
|
import org.hibernate.dialect.Replacer;
|
||||||
import org.hibernate.dialect.RowLockStrategy;
|
import org.hibernate.dialect.RowLockStrategy;
|
||||||
|
@ -94,6 +93,7 @@ import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
|
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType;
|
import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType;
|
||||||
|
@ -777,7 +777,12 @@ public class OracleLegacyDialect extends Dialect {
|
||||||
|
|
||||||
typeContributions.contributeJdbcType( OracleBooleanJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( OracleBooleanJdbcType.INSTANCE );
|
||||||
typeContributions.contributeJdbcType( OracleXmlJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( OracleXmlJdbcType.INSTANCE );
|
||||||
typeContributions.contributeJdbcType( OracleStructJdbcType.INSTANCE );
|
if ( OracleJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
|
typeContributions.contributeJdbcType( OracleJdbcHelper.getStructJdbcType( serviceRegistry ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
typeContributions.contributeJdbcType( OracleReflectionStructJdbcType.INSTANCE );
|
||||||
|
}
|
||||||
|
|
||||||
if ( getVersion().isSameOrAfter( 12 ) ) {
|
if ( getVersion().isSameOrAfter( 12 ) ) {
|
||||||
// account for Oracle's deprecated support for LONGVARBINARY
|
// account for Oracle's deprecated support for LONGVARBINARY
|
||||||
|
@ -802,7 +807,12 @@ public class OracleLegacyDialect extends Dialect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typeContributions.contributeJdbcType( OracleArrayJdbcType.INSTANCE );
|
if ( OracleJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
|
typeContributions.contributeJdbcType( OracleJdbcHelper.getArrayJdbcType( serviceRegistry ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
typeContributions.contributeJdbcType( ArrayJdbcType.INSTANCE );
|
||||||
|
}
|
||||||
// Oracle requires a custom binder for binding untyped nulls with the NULL type
|
// Oracle requires a custom binder for binding untyped nulls with the NULL type
|
||||||
typeContributions.contributeJdbcType( NullJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( NullJdbcType.INSTANCE );
|
||||||
typeContributions.contributeJdbcType( ObjectNullAsNullTypeJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( ObjectNullAsNullTypeJdbcType.INSTANCE );
|
||||||
|
@ -984,7 +994,7 @@ public class OracleLegacyDialect extends Dialect {
|
||||||
@Override
|
@Override
|
||||||
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
|
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
|
||||||
// register the type of the out param - an Oracle specific type
|
// register the type of the out param - an Oracle specific type
|
||||||
statement.registerOutParameter( col, OracleTypesHelper.INSTANCE.getOracleCursorTypeSqlType() );
|
statement.registerOutParameter( col, OracleTypes.CURSOR );
|
||||||
col++;
|
col++;
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
@ -1371,7 +1381,7 @@ public class OracleLegacyDialect extends Dialect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int registerResultSetOutParameter(CallableStatement statement, String name) throws SQLException {
|
public int registerResultSetOutParameter(CallableStatement statement, String name) throws SQLException {
|
||||||
statement.registerOutParameter( name, OracleTypesHelper.INSTANCE.getOracleCursorTypeSqlType() );
|
statement.registerOutParameter( name, OracleTypes.CURSOR );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,17 +30,12 @@ import org.hibernate.dialect.DatabaseVersion;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.NationalizationSupport;
|
import org.hibernate.dialect.NationalizationSupport;
|
||||||
import org.hibernate.dialect.OracleDialect;
|
import org.hibernate.dialect.OracleDialect;
|
||||||
|
import org.hibernate.dialect.PgJdbcHelper;
|
||||||
import org.hibernate.dialect.PostgreSQLCastingInetJdbcType;
|
import org.hibernate.dialect.PostgreSQLCastingInetJdbcType;
|
||||||
import org.hibernate.dialect.PostgreSQLCastingIntervalSecondJdbcType;
|
import org.hibernate.dialect.PostgreSQLCastingIntervalSecondJdbcType;
|
||||||
import org.hibernate.dialect.PostgreSQLCastingJsonJdbcType;
|
import org.hibernate.dialect.PostgreSQLCastingJsonJdbcType;
|
||||||
import org.hibernate.dialect.PostgreSQLCastingStructJdbcType;
|
|
||||||
import org.hibernate.dialect.PostgreSQLDriverKind;
|
import org.hibernate.dialect.PostgreSQLDriverKind;
|
||||||
import org.hibernate.dialect.PostgreSQLInetJdbcType;
|
import org.hibernate.dialect.PostgreSQLStructCastingJdbcType;
|
||||||
import org.hibernate.dialect.PostgreSQLIntervalSecondJdbcType;
|
|
||||||
import org.hibernate.dialect.PostgreSQLJsonJdbcType;
|
|
||||||
import org.hibernate.dialect.PostgreSQLJsonbJdbcType;
|
|
||||||
import org.hibernate.dialect.PostgreSQLPGObjectJdbcType;
|
|
||||||
import org.hibernate.dialect.PostgreSQLStructJdbcType;
|
|
||||||
import org.hibernate.dialect.Replacer;
|
import org.hibernate.dialect.Replacer;
|
||||||
import org.hibernate.dialect.RowLockStrategy;
|
import org.hibernate.dialect.RowLockStrategy;
|
||||||
import org.hibernate.dialect.SelectItemReferenceStrategy;
|
import org.hibernate.dialect.SelectItemReferenceStrategy;
|
||||||
|
@ -1334,15 +1329,15 @@ public class PostgreSQLLegacyDialect extends Dialect {
|
||||||
jdbcTypeRegistry.addDescriptor( XmlJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptor( XmlJdbcType.INSTANCE );
|
||||||
|
|
||||||
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
||||||
if ( PostgreSQLPGObjectJdbcType.isUsable() ) {
|
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLInetJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getInetJdbcType( serviceRegistry ) );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLIntervalSecondJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getIntervalJdbcType( serviceRegistry ) );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLStructJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getStructJdbcType( serviceRegistry ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingInetJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingInetJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingStructJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLStructCastingJdbcType.INSTANCE );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( getVersion().isSameOrAfter( 8, 2 ) ) {
|
if ( getVersion().isSameOrAfter( 8, 2 ) ) {
|
||||||
|
@ -1350,16 +1345,16 @@ public class PostgreSQLLegacyDialect extends Dialect {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||||
if ( getVersion().isSameOrAfter( 9, 2 ) ) {
|
if ( getVersion().isSameOrAfter( 9, 2 ) ) {
|
||||||
if ( getVersion().isSameOrAfter( 9, 4 ) ) {
|
if ( getVersion().isSameOrAfter( 9, 4 ) ) {
|
||||||
if ( PostgreSQLPGObjectJdbcType.isUsable() ) {
|
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLJsonbJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getJsonbJdbcType( serviceRegistry ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingJsonJdbcType.JSONB_INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingJsonJdbcType.JSONB_INSTANCE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( PostgreSQLPGObjectJdbcType.isUsable() ) {
|
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLJsonJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getJsonJdbcType( serviceRegistry ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingJsonJdbcType.JSON_INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingJsonJdbcType.JSON_INSTANCE );
|
||||||
|
@ -1371,7 +1366,7 @@ public class PostgreSQLLegacyDialect extends Dialect {
|
||||||
else {
|
else {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingInetJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingInetJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingStructJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLStructCastingJdbcType.INSTANCE );
|
||||||
|
|
||||||
if ( getVersion().isSameOrAfter( 8, 2 ) ) {
|
if ( getVersion().isSameOrAfter( 8, 2 ) ) {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||||
|
|
|
@ -45,6 +45,7 @@ dependencies {
|
||||||
compileOnly jakartaLibs.jsonbApi
|
compileOnly jakartaLibs.jsonbApi
|
||||||
compileOnly libs.jackson
|
compileOnly libs.jackson
|
||||||
compileOnly libs.jacksonXml
|
compileOnly libs.jacksonXml
|
||||||
|
compileOnly dbLibs.postgresql
|
||||||
|
|
||||||
testImplementation project(':hibernate-testing')
|
testImplementation project(':hibernate-testing')
|
||||||
testImplementation project(':hibernate-ant')
|
testImplementation project(':hibernate-ant')
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.SQLException;
|
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
|
||||||
import org.hibernate.type.SqlTypes;
|
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
|
||||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christian Beikov
|
|
||||||
*/
|
|
||||||
public abstract class AbstractPostgreSQLJsonJdbcType extends PostgreSQLPGObjectJdbcType implements AggregateJdbcType {
|
|
||||||
|
|
||||||
private final EmbeddableMappingType embeddableMappingType;
|
|
||||||
|
|
||||||
public AbstractPostgreSQLJsonJdbcType(EmbeddableMappingType embeddableMappingType, String typeName) {
|
|
||||||
super( typeName, SqlTypes.JSON );
|
|
||||||
this.embeddableMappingType = embeddableMappingType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EmbeddableMappingType getEmbeddableMappingType() {
|
|
||||||
return embeddableMappingType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected <X> X fromString(String string, JavaType<X> javaType, WrapperOptions options) throws SQLException {
|
|
||||||
if ( embeddableMappingType != null ) {
|
|
||||||
return JsonHelper.fromString(
|
|
||||||
embeddableMappingType,
|
|
||||||
string,
|
|
||||||
javaType.getJavaTypeClass() != Object[].class,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().fromString(
|
|
||||||
string,
|
|
||||||
javaType,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected <X> String toString(X value, JavaType<X> javaType, WrapperOptions options) {
|
|
||||||
if ( embeddableMappingType != null ) {
|
|
||||||
return JsonHelper.toString( embeddableMappingType, value, options );
|
|
||||||
}
|
|
||||||
return options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().toString(
|
|
||||||
value,
|
|
||||||
javaType,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object createJdbcValue(Object domainValue, WrapperOptions options) throws SQLException {
|
|
||||||
assert embeddableMappingType != null;
|
|
||||||
return JsonHelper.toString( embeddableMappingType, domainValue, options );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] extractJdbcValues(Object rawJdbcValue, WrapperOptions options) throws SQLException {
|
|
||||||
assert embeddableMappingType != null;
|
|
||||||
return JsonHelper.fromString( embeddableMappingType, (String) rawJdbcValue, false, options );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* 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.metamodel.mapping.EmbeddableMappingType;
|
||||||
|
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.JsonJdbcType;
|
||||||
|
|
||||||
|
import org.postgresql.util.PGobject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public abstract class AbstractPostgreSQLJsonPGObjectType extends JsonJdbcType {
|
||||||
|
|
||||||
|
private final boolean jsonb;
|
||||||
|
protected AbstractPostgreSQLJsonPGObjectType(EmbeddableMappingType embeddableMappingType, boolean jsonb) {
|
||||||
|
super( embeddableMappingType );
|
||||||
|
this.jsonb = jsonb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getJdbcTypeCode() {
|
||||||
|
return SqlTypes.OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 stringValue = ( (AbstractPostgreSQLJsonPGObjectType) getJdbcType() ).toString(
|
||||||
|
value,
|
||||||
|
getJavaType(),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
final PGobject holder = new PGobject();
|
||||||
|
holder.setType( jsonb ? "jsonb" : "json" );
|
||||||
|
holder.setValue( stringValue );
|
||||||
|
st.setObject( index, holder );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||||
|
throws SQLException {
|
||||||
|
final String stringValue = ( (AbstractPostgreSQLJsonPGObjectType) getJdbcType() ).toString(
|
||||||
|
value,
|
||||||
|
getJavaType(),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
final PGobject holder = new PGobject();
|
||||||
|
holder.setType( jsonb ? "jsonb" : "json" );
|
||||||
|
holder.setValue( stringValue );
|
||||||
|
st.setObject( name, holder );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@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.getObject( paramIndex ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||||
|
return getObject( statement.getObject( index ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
|
||||||
|
throws SQLException {
|
||||||
|
return getObject( statement.getObject( name ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
private X getObject(Object object, WrapperOptions options) throws SQLException {
|
||||||
|
if ( object == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ( (AbstractPostgreSQLJsonPGObjectType) getJdbcType() ).fromString(
|
||||||
|
object.toString(),
|
||||||
|
getJavaType(),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.sql.CallableStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
@ -30,6 +34,7 @@ import org.hibernate.metamodel.mapping.MappingType;
|
||||||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||||
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.spi.StringBuilderSqlAppender;
|
import org.hibernate.sql.ast.spi.StringBuilderSqlAppender;
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
|
@ -39,6 +44,7 @@ import org.hibernate.type.descriptor.java.JavaType;
|
||||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||||
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
|
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
|
||||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate;
|
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate;
|
||||||
|
@ -54,9 +60,7 @@ import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTimestampWithM
|
||||||
*
|
*
|
||||||
* @author Christian Beikov
|
* @author Christian Beikov
|
||||||
*/
|
*/
|
||||||
public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType implements AggregateJdbcType {
|
public abstract class AbstractPostgreSQLStructJdbcType implements AggregateJdbcType {
|
||||||
|
|
||||||
public static final PostgreSQLStructJdbcType INSTANCE = new PostgreSQLStructJdbcType( null, null, null );
|
|
||||||
|
|
||||||
private static final DateTimeFormatter LOCAL_DATE_TIME;
|
private static final DateTimeFormatter LOCAL_DATE_TIME;
|
||||||
static {
|
static {
|
||||||
|
@ -83,14 +87,16 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
||||||
.appendOffset( "+HH:mm", "+00" )
|
.appendOffset( "+HH:mm", "+00" )
|
||||||
.toFormatter();
|
.toFormatter();
|
||||||
}
|
}
|
||||||
|
private final String typeName;
|
||||||
private final int[] orderMapping;
|
private final int[] orderMapping;
|
||||||
private final int[] inverseOrderMapping;
|
private final int[] inverseOrderMapping;
|
||||||
private final EmbeddableMappingType embeddableMappingType;
|
private final EmbeddableMappingType embeddableMappingType;
|
||||||
private final ValueExtractor<Object[]> objectArrayExtractor;
|
|
||||||
|
|
||||||
public PostgreSQLStructJdbcType(EmbeddableMappingType embeddableMappingType, String typeName, int[] orderMapping) {
|
protected AbstractPostgreSQLStructJdbcType(
|
||||||
super( typeName, SqlTypes.STRUCT );
|
EmbeddableMappingType embeddableMappingType,
|
||||||
|
String typeName,
|
||||||
|
int[] orderMapping) {
|
||||||
|
this.typeName = typeName;
|
||||||
this.embeddableMappingType = embeddableMappingType;
|
this.embeddableMappingType = embeddableMappingType;
|
||||||
this.orderMapping = orderMapping;
|
this.orderMapping = orderMapping;
|
||||||
if ( orderMapping == null ) {
|
if ( orderMapping == null ) {
|
||||||
|
@ -103,10 +109,6 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
||||||
}
|
}
|
||||||
this.inverseOrderMapping = inverseOrderMapping;
|
this.inverseOrderMapping = inverseOrderMapping;
|
||||||
}
|
}
|
||||||
// We cache the extractor for Obje
|
|
||||||
// We cache the extractor for Object[] here
|
|
||||||
// since that is used in AggregateEmbeddableFetchImpl and AggregateEmbeddableResultImpl
|
|
||||||
this.objectArrayExtractor = super.getExtractor( new UnknownBasicJavaType<>( Object[].class ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -114,20 +116,8 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
||||||
return SqlTypes.STRUCT;
|
return SqlTypes.STRUCT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public String getTypeName() {
|
||||||
public AggregateJdbcType resolveAggregateJdbcType(
|
return typeName;
|
||||||
EmbeddableMappingType mappingType,
|
|
||||||
String sqlType,
|
|
||||||
RuntimeModelCreationContext creationContext) {
|
|
||||||
return new PostgreSQLStructJdbcType(
|
|
||||||
mappingType,
|
|
||||||
sqlType,
|
|
||||||
creationContext.getBootModel()
|
|
||||||
.getDatabase()
|
|
||||||
.getDefaultNamespace()
|
|
||||||
.locateUserDefinedType( Identifier.toIdentifier( sqlType ) )
|
|
||||||
.getOrderMapping()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -151,14 +141,36 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
|
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
|
||||||
if ( javaType.getJavaTypeClass() == Object[].class ) {
|
return new BasicExtractor<>( javaType, this ) {
|
||||||
//noinspection unchecked
|
@Override
|
||||||
return (ValueExtractor<X>) objectArrayExtractor;
|
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||||
}
|
return getObject( rs.getObject( paramIndex ), options );
|
||||||
return super.getExtractor( javaType );
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||||
|
return getObject( statement.getObject( index ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
|
||||||
|
throws SQLException {
|
||||||
|
return getObject( statement.getObject( name ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
private X getObject(Object object, WrapperOptions options) throws SQLException {
|
||||||
|
if ( object == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ( (AbstractPostgreSQLStructJdbcType) getJdbcType() ).fromString(
|
||||||
|
object.toString(),
|
||||||
|
getJavaType(),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected <X> X fromString(String string, JavaType<X> javaType, WrapperOptions options) throws SQLException {
|
protected <X> X fromString(String string, JavaType<X> javaType, WrapperOptions options) throws SQLException {
|
||||||
if ( string == null ) {
|
if ( string == null ) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -407,9 +419,9 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
||||||
if ( string.charAt( i + 1 ) == '(' ) {
|
if ( string.charAt( i + 1 ) == '(' ) {
|
||||||
// This could be a nested struct
|
// This could be a nested struct
|
||||||
final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping();
|
final JdbcMapping jdbcMapping = getJdbcValueSelectable( column ).getJdbcMapping();
|
||||||
if ( jdbcMapping.getJdbcType() instanceof PostgreSQLStructJdbcType ) {
|
if ( jdbcMapping.getJdbcType() instanceof AbstractPostgreSQLStructJdbcType ) {
|
||||||
final PostgreSQLStructJdbcType structJdbcType;
|
final AbstractPostgreSQLStructJdbcType structJdbcType;
|
||||||
structJdbcType = (PostgreSQLStructJdbcType) jdbcMapping.getJdbcType();
|
structJdbcType = (AbstractPostgreSQLStructJdbcType) jdbcMapping.getJdbcType();
|
||||||
final Object[] subValues = new Object[structJdbcType.embeddableMappingType.getJdbcValueCount()];
|
final Object[] subValues = new Object[structJdbcType.embeddableMappingType.getJdbcValueCount()];
|
||||||
final int subEnd = structJdbcType.deserializeStruct(
|
final int subEnd = structJdbcType.deserializeStruct(
|
||||||
string,
|
string,
|
||||||
|
@ -655,7 +667,6 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected <X> String toString(X value, JavaType<X> javaType, WrapperOptions options) {
|
protected <X> String toString(X value, JavaType<X> javaType, WrapperOptions options) {
|
||||||
if ( value == null ) {
|
if ( value == null ) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -718,7 +729,7 @@ public class PostgreSQLStructJdbcType extends PostgreSQLPGObjectJdbcType impleme
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
appender.quoteStart();
|
appender.quoteStart();
|
||||||
( (PostgreSQLStructJdbcType) aggregateMapping.getJdbcMapping().getJdbcType() ).serializeStructTo(
|
( (AbstractPostgreSQLStructJdbcType) aggregateMapping.getJdbcMapping().getJdbcType() ).serializeStructTo(
|
||||||
appender,
|
appender,
|
||||||
attributeValue,
|
attributeValue,
|
||||||
options
|
options
|
|
@ -342,10 +342,10 @@ public class CockroachDialect extends Dialect {
|
||||||
jdbcTypeRegistry.addDescriptor( TIMESTAMP_UTC, InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptor( TIMESTAMP_UTC, InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
||||||
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||||
if ( PostgreSQLPGObjectJdbcType.isUsable() ) {
|
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLIntervalSecondJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getIntervalJdbcType( serviceRegistry ) );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLInetJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getInetJdbcType( serviceRegistry ) );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLJsonbJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getJsonbJdbcType( serviceRegistry ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
||||||
|
|
|
@ -7,15 +7,14 @@
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.sql.CallableStatement;
|
import java.sql.CallableStatement;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
|
@ -29,7 +28,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
|
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import oracle.jdbc.OracleConnection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for {@link Types#ARRAY ARRAY} handling.
|
* Descriptor for {@link Types#ARRAY ARRAY} handling.
|
||||||
|
@ -39,43 +38,14 @@ import org.jboss.logging.Logger;
|
||||||
*/
|
*/
|
||||||
public class OracleArrayJdbcType extends ArrayJdbcType {
|
public class OracleArrayJdbcType extends ArrayJdbcType {
|
||||||
|
|
||||||
public static final OracleArrayJdbcType INSTANCE = new OracleArrayJdbcType( null, ObjectJdbcType.INSTANCE );
|
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, OracleArrayJdbcType.class.getName() );
|
|
||||||
private static final ClassValue<Method> NAME_BINDER = new ClassValue<Method>() {
|
|
||||||
@Override
|
|
||||||
protected Method computeValue(Class<?> type) {
|
|
||||||
try {
|
|
||||||
return type.getMethod( "setArray", String.class, java.sql.Array.class );
|
|
||||||
}
|
|
||||||
catch ( Exception ex ) {
|
|
||||||
// add logging? Did we get NoSuchMethodException or SecurityException?
|
|
||||||
// Doesn't matter which. We can't use it.
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private static final Class<?> ORACLE_CONNECTION_CLASS;
|
|
||||||
private static final Method CREATE_ARRAY_METHOD;
|
|
||||||
|
|
||||||
static {
|
|
||||||
Class<?> oracleConnectionClass = null;
|
|
||||||
Method createArrayMethod = null;
|
|
||||||
try {
|
|
||||||
oracleConnectionClass = Class.forName( "oracle.jdbc.OracleConnection" );
|
|
||||||
createArrayMethod = oracleConnectionClass.getMethod( "createOracleArray", String.class, Object.class );
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
// Ignore since #resolveType should be called anyway and the OracleArrayJdbcType shouldn't be used
|
|
||||||
// if driver classes are unavailable
|
|
||||||
LOG.warn( "Oracle JDBC driver classes are inaccessible and thus, certain DDL types like ARRAY can not be used!", e );
|
|
||||||
}
|
|
||||||
ORACLE_CONNECTION_CLASS = oracleConnectionClass;
|
|
||||||
CREATE_ARRAY_METHOD = createArrayMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String typeName;
|
private final String typeName;
|
||||||
|
|
||||||
public OracleArrayJdbcType(String typeName, JdbcType elementJdbcType) {
|
public OracleArrayJdbcType() {
|
||||||
|
super( ObjectJdbcType.INSTANCE );
|
||||||
|
this.typeName = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OracleArrayJdbcType(String typeName, JdbcType elementJdbcType) {
|
||||||
super( elementJdbcType );
|
super( elementJdbcType );
|
||||||
this.typeName = typeName;
|
this.typeName = typeName;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +71,7 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( typeName == null || CREATE_ARRAY_METHOD == null ) {
|
if ( typeName == null ) {
|
||||||
// Fallback to XML type for the representation of arrays as the native JSON type was only introduced in 21
|
// Fallback to XML type for the representation of arrays as the native JSON type was only introduced in 21
|
||||||
// Also, use the XML type if the Oracle JDBC driver classes are not visible
|
// Also, use the XML type if the Oracle JDBC driver classes are not visible
|
||||||
return typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.SQLXML );
|
return typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.SQLXML );
|
||||||
|
@ -111,9 +81,6 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ValueBinder<X> getBinder(final JavaType<X> javaTypeDescriptor) {
|
public <X> ValueBinder<X> getBinder(final JavaType<X> javaTypeDescriptor) {
|
||||||
if ( CREATE_ARRAY_METHOD == null ) {
|
|
||||||
throw new RuntimeException( "OracleArrayJdbcType shouldn't be used since JDBC driver classes are not visible." );
|
|
||||||
}
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
final BasicPluralJavaType<X> containerJavaType = (BasicPluralJavaType<X>) javaTypeDescriptor;
|
final BasicPluralJavaType<X> containerJavaType = (BasicPluralJavaType<X>) javaTypeDescriptor;
|
||||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||||
|
@ -137,25 +104,11 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
|
||||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
final java.sql.Array arr = getArray( value, containerJavaType, options );
|
final java.sql.Array arr = getArray( value, containerJavaType, options );
|
||||||
final Method nameBinder = NAME_BINDER.get( st.getClass() );
|
|
||||||
if ( nameBinder == null ) {
|
|
||||||
try {
|
|
||||||
st.setObject( name, arr, Types.ARRAY );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (SQLException ex) {
|
|
||||||
throw new HibernateException( "JDBC driver does not support named parameters for setArray. Use positional.", ex );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Not that it's supposed to have setArray(String,Array) by standard.
|
|
||||||
// There are numerous missing methods that only have versions for positional parameter,
|
|
||||||
// but not named ones.
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
nameBinder.invoke( st, name, arr );
|
st.setObject( name, arr, Types.ARRAY );
|
||||||
}
|
}
|
||||||
catch ( Throwable t ) {
|
catch (SQLException ex) {
|
||||||
throw new HibernateException( t );
|
throw new HibernateException( "JDBC driver does not support named parameters for setArray. Use positional.", ex );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,10 +124,10 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
|
||||||
final Object[] objects = javaTypeDescriptor.unwrap( value, arrayClass, options );
|
final Object[] objects = javaTypeDescriptor.unwrap( value, arrayClass, options );
|
||||||
|
|
||||||
final SharedSessionContractImplementor session = options.getSession();
|
final SharedSessionContractImplementor session = options.getSession();
|
||||||
final Object oracleConnection = session.getJdbcCoordinator().getLogicalConnection().getPhysicalConnection()
|
final OracleConnection oracleConnection = session.getJdbcCoordinator().getLogicalConnection().getPhysicalConnection()
|
||||||
.unwrap( ORACLE_CONNECTION_CLASS );
|
.unwrap( OracleConnection.class );
|
||||||
try {
|
try {
|
||||||
return (java.sql.Array) CREATE_ARRAY_METHOD.invoke( oracleConnection, typeName, objects );
|
return oracleConnection.createOracleArray( typeName, objects );
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
throw new HibernateException( "Couldn't create a java.sql.Array", e );
|
throw new HibernateException( "Couldn't create a java.sql.Array", e );
|
||||||
|
@ -194,11 +147,11 @@ public class OracleArrayJdbcType extends ArrayJdbcType {
|
||||||
|
|
||||||
OracleArrayJdbcType that = (OracleArrayJdbcType) o;
|
OracleArrayJdbcType that = (OracleArrayJdbcType) o;
|
||||||
|
|
||||||
return typeName.equals( that.typeName );
|
return Objects.equals( typeName, that.typeName );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return typeName.hashCode();
|
return typeName != null ? typeName.hashCode() : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@ import org.hibernate.type.NullType;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
|
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.NullJdbcType;
|
import org.hibernate.type.descriptor.jdbc.NullJdbcType;
|
||||||
|
@ -782,7 +783,12 @@ public class OracleDialect extends Dialect {
|
||||||
|
|
||||||
typeContributions.contributeJdbcType( OracleBooleanJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( OracleBooleanJdbcType.INSTANCE );
|
||||||
typeContributions.contributeJdbcType( OracleXmlJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( OracleXmlJdbcType.INSTANCE );
|
||||||
typeContributions.contributeJdbcType( OracleStructJdbcType.INSTANCE );
|
if ( OracleJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
|
typeContributions.contributeJdbcType( OracleJdbcHelper.getStructJdbcType( serviceRegistry ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
typeContributions.contributeJdbcType( OracleReflectionStructJdbcType.INSTANCE );
|
||||||
|
}
|
||||||
|
|
||||||
if ( getVersion().isSameOrAfter( 12 ) ) {
|
if ( getVersion().isSameOrAfter( 12 ) ) {
|
||||||
// account for Oracle's deprecated support for LONGVARBINARY
|
// account for Oracle's deprecated support for LONGVARBINARY
|
||||||
|
@ -807,7 +813,12 @@ public class OracleDialect extends Dialect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typeContributions.contributeJdbcType( OracleArrayJdbcType.INSTANCE );
|
if ( OracleJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
|
typeContributions.contributeJdbcType( OracleJdbcHelper.getArrayJdbcType( serviceRegistry ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
typeContributions.contributeJdbcType( OracleReflectionStructJdbcType.INSTANCE );
|
||||||
|
}
|
||||||
// Oracle requires a custom binder for binding untyped nulls with the NULL type
|
// Oracle requires a custom binder for binding untyped nulls with the NULL type
|
||||||
typeContributions.contributeJdbcType( NullJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( NullJdbcType.INSTANCE );
|
||||||
typeContributions.contributeJdbcType( ObjectNullAsNullTypeJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( ObjectNullAsNullTypeJdbcType.INSTANCE );
|
||||||
|
@ -976,7 +987,7 @@ public class OracleDialect extends Dialect {
|
||||||
@Override
|
@Override
|
||||||
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
|
public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException {
|
||||||
// register the type of the out param - an Oracle specific type
|
// register the type of the out param - an Oracle specific type
|
||||||
statement.registerOutParameter( col, OracleTypesHelper.INSTANCE.getOracleCursorTypeSqlType() );
|
statement.registerOutParameter( col, OracleTypes.CURSOR );
|
||||||
col++;
|
col++;
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
@ -1374,7 +1385,7 @@ public class OracleDialect extends Dialect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int registerResultSetOutParameter(CallableStatement statement, String name) throws SQLException {
|
public int registerResultSetOutParameter(CallableStatement statement, String name) throws SQLException {
|
||||||
statement.registerOutParameter( name, OracleTypesHelper.INSTANCE.getOracleCursorTypeSqlType() );
|
statement.registerOutParameter( name, OracleTypes.CURSOR );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateError;
|
||||||
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
|
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following class provides some convenience methods for accessing JdbcType instance,
|
||||||
|
* that are loaded into the app class loader, where they have access to the JDBC driver classes.
|
||||||
|
*
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public class OracleJdbcHelper {
|
||||||
|
|
||||||
|
public static boolean isUsable(ServiceRegistry serviceRegistry) {
|
||||||
|
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||||
|
try {
|
||||||
|
classLoaderService.classForName( "oracle.jdbc.OracleConnection" );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (ClassLoadingException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JdbcType getArrayJdbcType(ServiceRegistry serviceRegistry) {
|
||||||
|
return createJdbcType( serviceRegistry, "org.hibernate.dialect.OracleArrayJdbcType" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JdbcType getStructJdbcType(ServiceRegistry serviceRegistry) {
|
||||||
|
return createJdbcType( serviceRegistry, "org.hibernate.dialect.OracleStructJdbcType" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JdbcType createJdbcType(ServiceRegistry serviceRegistry, String className) {
|
||||||
|
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||||
|
try {
|
||||||
|
final Class<?> clazz = classLoaderService.classForName( className );
|
||||||
|
final Constructor<?> constructor = clazz.getConstructor();
|
||||||
|
return (JdbcType) constructor.newInstance();
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException e) {
|
||||||
|
throw new HibernateError( "Class does not have an empty constructor", e );
|
||||||
|
}
|
||||||
|
catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||||
|
throw new HibernateError( "Could not construct JdbcType", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* 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.lang.reflect.Method;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.boot.model.naming.Identifier;
|
||||||
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public class OracleReflectionStructJdbcType extends StructJdbcType {
|
||||||
|
public static final AggregateJdbcType INSTANCE = new OracleReflectionStructJdbcType();
|
||||||
|
|
||||||
|
private static final ClassValue<Method> RAW_JDBC_TRANSFORMER = new ClassValue<>() {
|
||||||
|
@Override
|
||||||
|
protected Method computeValue(Class<?> type) {
|
||||||
|
if ( "oracle.sql.TIMESTAMPTZ".equals( type.getName() ) ) {
|
||||||
|
try {
|
||||||
|
return type.getMethod( "offsetDateTimeValue", Connection.class );
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private OracleReflectionStructJdbcType() {
|
||||||
|
// The default instance is for reading only and will return an Object[]
|
||||||
|
this( null, null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public OracleReflectionStructJdbcType(EmbeddableMappingType embeddableMappingType, String typeName, int[] orderMapping) {
|
||||||
|
super(
|
||||||
|
embeddableMappingType,
|
||||||
|
typeName == null ? null : typeName.toUpperCase( Locale.ROOT ),
|
||||||
|
orderMapping
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AggregateJdbcType resolveAggregateJdbcType(
|
||||||
|
EmbeddableMappingType mappingType,
|
||||||
|
String sqlType,
|
||||||
|
RuntimeModelCreationContext creationContext) {
|
||||||
|
return new OracleReflectionStructJdbcType(
|
||||||
|
mappingType,
|
||||||
|
sqlType,
|
||||||
|
creationContext.getBootModel()
|
||||||
|
.getDatabase()
|
||||||
|
.getDefaultNamespace()
|
||||||
|
.locateUserDefinedType( Identifier.toIdentifier( sqlType ) )
|
||||||
|
.getOrderMapping()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object transformRawJdbcValue(Object rawJdbcValue, WrapperOptions options) {
|
||||||
|
Method rawJdbcTransformer = RAW_JDBC_TRANSFORMER.get( rawJdbcValue.getClass() );
|
||||||
|
if ( rawJdbcTransformer == null ) {
|
||||||
|
return rawJdbcValue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return rawJdbcTransformer.invoke(
|
||||||
|
rawJdbcValue,
|
||||||
|
options.getSession()
|
||||||
|
.getJdbcCoordinator()
|
||||||
|
.getLogicalConnection()
|
||||||
|
.getPhysicalConnection()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new HibernateException( "Could not transform the raw jdbc value", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,88 +6,33 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.sql.CallableStatement;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Struct;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.boot.model.naming.Identifier;
|
import org.hibernate.boot.model.naming.Identifier;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
|
||||||
import org.hibernate.metamodel.mapping.MappingType;
|
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
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.WrapperOptions;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
|
||||||
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
|
|
||||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
|
||||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
|
||||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
|
||||||
|
import oracle.sql.TIMESTAMPTZ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christian Beikov
|
* @author Christian Beikov
|
||||||
*/
|
*/
|
||||||
public class OracleStructJdbcType implements AggregateJdbcType {
|
public class OracleStructJdbcType extends StructJdbcType {
|
||||||
|
|
||||||
public static final AggregateJdbcType INSTANCE = new OracleStructJdbcType();
|
public OracleStructJdbcType() {
|
||||||
|
|
||||||
private static final ClassValue<Method> RAW_JDBC_TRANSFORMER = new ClassValue<>() {
|
|
||||||
@Override
|
|
||||||
protected Method computeValue(Class<?> type) {
|
|
||||||
if ( "oracle.sql.TIMESTAMPTZ".equals( type.getName() ) ) {
|
|
||||||
try {
|
|
||||||
return type.getMethod( "offsetDateTimeValue", Connection.class );
|
|
||||||
}
|
|
||||||
catch (NoSuchMethodException e) {
|
|
||||||
throw new RuntimeException( e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final String oracleTypeName;
|
|
||||||
private final int[] orderMapping;
|
|
||||||
private final int[] inverseOrderMapping;
|
|
||||||
private final EmbeddableMappingType embeddableMappingType;
|
|
||||||
private final ValueExtractor<Object[]> objectArrayExtractor;
|
|
||||||
|
|
||||||
private OracleStructJdbcType() {
|
|
||||||
// The default instance is for reading only and will return an Object[]
|
// The default instance is for reading only and will return an Object[]
|
||||||
this( null, null, null );
|
this( null, null, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public OracleStructJdbcType(EmbeddableMappingType embeddableMappingType, String typeName, int[] orderMapping) {
|
private OracleStructJdbcType(EmbeddableMappingType embeddableMappingType, String typeName, int[] orderMapping) {
|
||||||
this.embeddableMappingType = embeddableMappingType;
|
super(
|
||||||
this.oracleTypeName = typeName == null ? null : typeName.toUpperCase( Locale.ROOT );
|
embeddableMappingType,
|
||||||
this.orderMapping = orderMapping;
|
typeName == null ? null : typeName.toUpperCase( Locale.ROOT ),
|
||||||
if ( orderMapping == null ) {
|
orderMapping
|
||||||
this.inverseOrderMapping = null;
|
);
|
||||||
}
|
|
||||||
else {
|
|
||||||
final int[] inverseOrderMapping = new int[orderMapping.length];
|
|
||||||
for ( int i = 0; i < orderMapping.length; i++ ) {
|
|
||||||
inverseOrderMapping[orderMapping[i]] = i;
|
|
||||||
}
|
|
||||||
this.inverseOrderMapping = inverseOrderMapping;
|
|
||||||
}
|
|
||||||
// We cache the extractor for Object[] here
|
|
||||||
// since that is used in AggregateEmbeddableFetchImpl and AggregateEmbeddableResultImpl
|
|
||||||
this.objectArrayExtractor = createBasicExtractor( new UnknownBasicJavaType<>( Object[].class ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getJdbcTypeCode() {
|
|
||||||
return SqlTypes.STRUCT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -107,329 +52,21 @@ public class OracleStructJdbcType implements AggregateJdbcType {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EmbeddableMappingType getEmbeddableMappingType() {
|
protected Object transformRawJdbcValue(Object rawJdbcValue, WrapperOptions options) {
|
||||||
return embeddableMappingType;
|
if ( rawJdbcValue.getClass() == TIMESTAMPTZ.class ) {
|
||||||
}
|
try {
|
||||||
|
return ( (TIMESTAMPTZ) rawJdbcValue ).offsetDateTimeValue(
|
||||||
@Override
|
options.getSession()
|
||||||
public <T> JavaType<T> getJdbcRecommendedJavaTypeMapping(
|
.getJdbcCoordinator()
|
||||||
Integer precision,
|
.getLogicalConnection()
|
||||||
Integer scale,
|
.getPhysicalConnection()
|
||||||
TypeConfiguration typeConfiguration) {
|
|
||||||
if ( embeddableMappingType == null ) {
|
|
||||||
return typeConfiguration.getJavaTypeRegistry().getDescriptor( Object[].class );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//noinspection unchecked
|
|
||||||
return (JavaType<T>) embeddableMappingType.getMappedJavaType();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerOutParameter(CallableStatement callableStatement, String name) throws SQLException {
|
|
||||||
callableStatement.registerOutParameter( name, getJdbcTypeCode(), oracleTypeName );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerOutParameter(CallableStatement callableStatement, int index) throws SQLException {
|
|
||||||
callableStatement.registerOutParameter( index, getJdbcTypeCode(), oracleTypeName );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object createJdbcValue(Object domainValue, WrapperOptions options) throws SQLException {
|
|
||||||
final Object[] jdbcValues = StructHelper.getJdbcValues(
|
|
||||||
embeddableMappingType,
|
|
||||||
orderMapping,
|
|
||||||
embeddableMappingType.getValues( domainValue ),
|
|
||||||
options
|
|
||||||
);
|
|
||||||
return options.getSession()
|
|
||||||
.getJdbcCoordinator()
|
|
||||||
.getLogicalConnection()
|
|
||||||
.getPhysicalConnection()
|
|
||||||
.createStruct( oracleTypeName, jdbcValues );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] extractJdbcValues(Object rawJdbcValue, WrapperOptions options) throws SQLException {
|
|
||||||
final Object[] attributes = ( (Struct) rawJdbcValue ).getAttributes();
|
|
||||||
wrapRawJdbcValues( embeddableMappingType, orderMapping, inverseOrderMapping, attributes, 0, options );
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 {
|
|
||||||
st.setObject( index, createJdbcValue( value, options ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
|
||||||
throws SQLException {
|
|
||||||
st.setObject( name, createJdbcValue( value, options ) );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
|
|
||||||
if ( javaType.getJavaTypeClass() == Object[].class ) {
|
|
||||||
//noinspection unchecked
|
|
||||||
return (ValueExtractor<X>) objectArrayExtractor;
|
|
||||||
}
|
|
||||||
return createBasicExtractor( javaType );
|
|
||||||
}
|
|
||||||
|
|
||||||
private <X> BasicExtractor<X> createBasicExtractor(JavaType<X> javaType) {
|
|
||||||
return new BasicExtractor<>( javaType, this ) {
|
|
||||||
@Override
|
|
||||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
|
||||||
return getValue( rs.getObject( paramIndex ), options );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
|
||||||
return getValue( statement.getObject( index ), options );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
|
|
||||||
throws SQLException {
|
|
||||||
return getValue( statement.getObject( name ), options );
|
|
||||||
}
|
|
||||||
|
|
||||||
private X getValue(Object object, WrapperOptions options) throws SQLException {
|
|
||||||
if ( object == null ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final Struct struct = (Struct) object;
|
|
||||||
final Object[] values = struct.getAttributes();
|
|
||||||
final boolean jdbcRepresentation = getJavaType().getJavaTypeClass() == Object[].class;
|
|
||||||
if ( jdbcRepresentation ) {
|
|
||||||
wrapRawJdbcValues( embeddableMappingType, orderMapping, inverseOrderMapping, values, 0, options );
|
|
||||||
//noinspection unchecked
|
|
||||||
return (X) values;
|
|
||||||
}
|
|
||||||
assert embeddableMappingType != null && embeddableMappingType.getJavaType() == getJavaType();
|
|
||||||
final Object[] attributeValues = getAttributeValues(
|
|
||||||
embeddableMappingType,
|
|
||||||
orderMapping,
|
|
||||||
values,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
//noinspection unchecked
|
|
||||||
return (X) embeddableMappingType.getRepresentationStrategy().getInstantiator().instantiate(
|
|
||||||
() -> attributeValues,
|
|
||||||
options.getSessionFactory()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
catch (Exception e) {
|
||||||
}
|
throw new HibernateException( "Could not transform the raw jdbc value", e );
|
||||||
|
|
||||||
private static Object[] getAttributeValues(
|
|
||||||
EmbeddableMappingType embeddableMappingType,
|
|
||||||
int[] orderMapping,
|
|
||||||
Object[] rawJdbcValues,
|
|
||||||
WrapperOptions options) throws SQLException {
|
|
||||||
final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();
|
|
||||||
final Object[] attributeValues;
|
|
||||||
if ( numberOfAttributeMappings != rawJdbcValues.length || orderMapping != null ) {
|
|
||||||
attributeValues = new Object[numberOfAttributeMappings];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
attributeValues = rawJdbcValues;
|
|
||||||
}
|
|
||||||
int jdbcIndex = 0;
|
|
||||||
for ( int i = 0; i < numberOfAttributeMappings; i++ ) {
|
|
||||||
final int attributeIndex;
|
|
||||||
if ( orderMapping == null ) {
|
|
||||||
attributeIndex = i;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
attributeIndex = orderMapping[i];
|
|
||||||
}
|
|
||||||
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( attributeIndex );
|
|
||||||
jdbcIndex += injectAttributeValue(
|
|
||||||
attributeMapping,
|
|
||||||
attributeValues,
|
|
||||||
attributeIndex,
|
|
||||||
rawJdbcValues,
|
|
||||||
jdbcIndex,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return attributeValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int injectAttributeValue(
|
|
||||||
AttributeMapping attributeMapping,
|
|
||||||
Object[] attributeValues,
|
|
||||||
int attributeIndex,
|
|
||||||
Object[] rawJdbcValues,
|
|
||||||
int jdbcIndex,
|
|
||||||
WrapperOptions options) throws SQLException {
|
|
||||||
final MappingType mappedType = attributeMapping.getMappedType();
|
|
||||||
final int jdbcValueCount;
|
|
||||||
final Object rawJdbcValue = rawJdbcValues[jdbcIndex];
|
|
||||||
if ( mappedType instanceof EmbeddableMappingType ) {
|
|
||||||
final EmbeddableMappingType embeddableMappingType = (EmbeddableMappingType) mappedType;
|
|
||||||
if ( embeddableMappingType.getAggregateMapping() != null ) {
|
|
||||||
jdbcValueCount = 1;
|
|
||||||
if ( rawJdbcValue == null ) {
|
|
||||||
attributeValues[attributeIndex] = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final AggregateJdbcType aggregateJdbcType = (AggregateJdbcType) embeddableMappingType.getAggregateMapping()
|
|
||||||
.getJdbcMapping()
|
|
||||||
.getJdbcType();
|
|
||||||
final Object[] subValues;
|
|
||||||
if ( aggregateJdbcType instanceof OracleStructJdbcType ) {
|
|
||||||
subValues = getAttributeValues(
|
|
||||||
embeddableMappingType,
|
|
||||||
( (OracleStructJdbcType) aggregateJdbcType ).orderMapping,
|
|
||||||
( (Struct) rawJdbcValue ).getAttributes(),
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
subValues = aggregateJdbcType.extractJdbcValues( rawJdbcValue, options );
|
|
||||||
}
|
|
||||||
attributeValues[attributeIndex] = embeddableMappingType.getRepresentationStrategy()
|
|
||||||
.getInstantiator()
|
|
||||||
.instantiate(
|
|
||||||
() -> subValues,
|
|
||||||
embeddableMappingType.findContainingEntityMapping()
|
|
||||||
.getEntityPersister()
|
|
||||||
.getFactory()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
jdbcValueCount = embeddableMappingType.getJdbcValueCount();
|
|
||||||
final Object[] jdbcValues = new Object[jdbcValueCount];
|
|
||||||
System.arraycopy( rawJdbcValues, jdbcIndex, jdbcValues, 0, jdbcValues.length );
|
|
||||||
final Object[] subValues = getAttributeValues( embeddableMappingType, null, jdbcValues, options );
|
|
||||||
attributeValues[attributeIndex] = embeddableMappingType.getRepresentationStrategy()
|
|
||||||
.getInstantiator()
|
|
||||||
.instantiate(
|
|
||||||
() -> subValues,
|
|
||||||
embeddableMappingType.findContainingEntityMapping()
|
|
||||||
.getEntityPersister()
|
|
||||||
.getFactory()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
return rawJdbcValue;
|
||||||
assert attributeMapping.getJdbcTypeCount() == 1;
|
|
||||||
jdbcValueCount = 1;
|
|
||||||
final JdbcMapping jdbcMapping = attributeMapping.getSingleJdbcMapping();
|
|
||||||
final Object jdbcValue;
|
|
||||||
if ( rawJdbcValue == null ) {
|
|
||||||
jdbcValue = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) {
|
|
||||||
case SqlTypes.TIMESTAMP_WITH_TIMEZONE:
|
|
||||||
case SqlTypes.TIMESTAMP_UTC:
|
|
||||||
// Only transform the raw jdbc value if it could be a TIMESTAMPTZ
|
|
||||||
jdbcValue = jdbcMapping.getJdbcJavaType()
|
|
||||||
.wrap( transformRawJdbcValue( rawJdbcValue, options ), options );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
jdbcValue = jdbcMapping.getJdbcJavaType().wrap( rawJdbcValue, options );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attributeValues[attributeIndex] = jdbcMapping.convertToDomainValue( jdbcValue );
|
|
||||||
}
|
|
||||||
return jdbcValueCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int wrapRawJdbcValues(
|
|
||||||
EmbeddableMappingType embeddableMappingType,
|
|
||||||
int[] orderMapping,
|
|
||||||
int[] inverseOrderMapping,
|
|
||||||
Object[] jdbcValues,
|
|
||||||
int jdbcIndex,
|
|
||||||
WrapperOptions options) throws SQLException {
|
|
||||||
final Object[] targetJdbcValues;
|
|
||||||
if ( orderMapping == null ) {
|
|
||||||
targetJdbcValues = jdbcValues;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
targetJdbcValues = jdbcValues.clone();
|
|
||||||
}
|
|
||||||
final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();
|
|
||||||
for ( int i = 0; i < numberOfAttributeMappings; i++ ) {
|
|
||||||
final AttributeMapping attributeMapping;
|
|
||||||
if ( orderMapping == null ) {
|
|
||||||
attributeMapping = embeddableMappingType.getAttributeMapping( i );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
attributeMapping = embeddableMappingType.getAttributeMapping( orderMapping[i] );
|
|
||||||
}
|
|
||||||
final MappingType mappedType = attributeMapping.getMappedType();
|
|
||||||
|
|
||||||
if ( mappedType instanceof EmbeddableMappingType ) {
|
|
||||||
final EmbeddableMappingType embeddableType = (EmbeddableMappingType) mappedType;
|
|
||||||
if ( embeddableType.getAggregateMapping() != null ) {
|
|
||||||
final AggregateJdbcType aggregateJdbcType = (AggregateJdbcType) embeddableType.getAggregateMapping()
|
|
||||||
.getJdbcMapping()
|
|
||||||
.getJdbcType();
|
|
||||||
final Object rawJdbcValue = targetJdbcValues[jdbcIndex];
|
|
||||||
targetJdbcValues[jdbcIndex] = aggregateJdbcType.extractJdbcValues( rawJdbcValue, options );
|
|
||||||
jdbcIndex++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
jdbcIndex = wrapRawJdbcValues( embeddableType, null, null, targetJdbcValues, jdbcIndex, options );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert attributeMapping.getJdbcTypeCount() == 1;
|
|
||||||
final Object rawJdbcValue = targetJdbcValues[jdbcIndex];
|
|
||||||
if ( rawJdbcValue != null ) {
|
|
||||||
final JdbcMapping jdbcMapping = attributeMapping.getSingleJdbcMapping();
|
|
||||||
switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) {
|
|
||||||
case SqlTypes.TIMESTAMP_WITH_TIMEZONE:
|
|
||||||
case SqlTypes.TIMESTAMP_UTC:
|
|
||||||
// Only transform the raw jdbc value if it could be a TIMESTAMPTZ
|
|
||||||
targetJdbcValues[jdbcIndex] = jdbcMapping.getJdbcJavaType()
|
|
||||||
.wrap( transformRawJdbcValue( rawJdbcValue, options ), options );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
targetJdbcValues[jdbcIndex] = jdbcMapping.getJdbcJavaType().wrap( rawJdbcValue, options );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jdbcIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( orderMapping != null ) {
|
|
||||||
StructHelper.orderJdbcValues( embeddableMappingType, inverseOrderMapping, targetJdbcValues, jdbcValues );
|
|
||||||
}
|
|
||||||
return jdbcIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object transformRawJdbcValue(Object rawJdbcValue, WrapperOptions options) {
|
|
||||||
Method rawJdbcTransformer = RAW_JDBC_TRANSFORMER.get( rawJdbcValue.getClass() );
|
|
||||||
if ( rawJdbcTransformer == null ) {
|
|
||||||
return rawJdbcValue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return rawJdbcTransformer.invoke(
|
|
||||||
rawJdbcValue,
|
|
||||||
options.getSession()
|
|
||||||
.getJdbcCoordinator()
|
|
||||||
.getLogicalConnection()
|
|
||||||
.getPhysicalConnection()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new HibernateException( "Could not transform the raw jdbc value", e );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,6 @@ package org.hibernate.dialect;
|
||||||
* The Oracle specific JDBC type code.
|
* The Oracle specific JDBC type code.
|
||||||
*/
|
*/
|
||||||
public class OracleTypes {
|
public class OracleTypes {
|
||||||
|
public static final int CURSOR = -10;
|
||||||
public static final int JSON = 2016;
|
public static final int JSON = 2016;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Helper for dealing with the OracleTypes class
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class OracleTypesHelper {
|
|
||||||
private static final CoreMessageLogger log = Logger.getMessageLogger( CoreMessageLogger.class, OracleTypesHelper.class.getName() );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Singleton access
|
|
||||||
*/
|
|
||||||
public static final OracleTypesHelper INSTANCE = new 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 final int oracleCursorTypeSqlType;
|
|
||||||
|
|
||||||
private OracleTypesHelper() {
|
|
||||||
int typeCode = -99;
|
|
||||||
try {
|
|
||||||
typeCode = extractOracleCursorTypeValue();
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int extractOracleCursorTypeValue() {
|
|
||||||
try {
|
|
||||||
return locateOracleTypesClass().getField( "CURSOR" ).getInt( null );
|
|
||||||
}
|
|
||||||
catch ( Exception se ) {
|
|
||||||
throw new HibernateException( "Unable to access OracleTypes.CURSOR value", se );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class locateOracleTypesClass() {
|
|
||||||
try {
|
|
||||||
return ReflectHelper.classForName( ORACLE_TYPES_CLASS_NAME );
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException e) {
|
|
||||||
try {
|
|
||||||
return ReflectHelper.classForName( DEPRECATED_ORACLE_TYPES_CLASS_NAME );
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException e2) {
|
|
||||||
throw new HibernateException(
|
|
||||||
String.format(
|
|
||||||
"Unable to locate OracleTypes class using either known FQN [%s, %s]",
|
|
||||||
ORACLE_TYPES_CLASS_NAME,
|
|
||||||
DEPRECATED_ORACLE_TYPES_CLASS_NAME
|
|
||||||
),
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOracleCursorTypeSqlType() {
|
|
||||||
return oracleCursorTypeSqlType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initial code as copied from Oracle8iDialect
|
|
||||||
//
|
|
||||||
// private int oracleCursorTypeSqlType = INIT_ORACLETYPES_CURSOR_VALUE;
|
|
||||||
//
|
|
||||||
// public int getOracleCursorTypeSqlType() {
|
|
||||||
// if ( oracleCursorTypeSqlType == INIT_ORACLETYPES_CURSOR_VALUE ) {
|
|
||||||
// // todo : is there really any reason to keep trying if this fails once?
|
|
||||||
// oracleCursorTypeSqlType = extractOracleCursorTypeValue();
|
|
||||||
// }
|
|
||||||
// return oracleCursorTypeSqlType;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private int extractOracleCursorTypeValue() {
|
|
||||||
// Class oracleTypesClass;
|
|
||||||
// try {
|
|
||||||
// oracleTypesClass = ReflectHelper.classForName( ORACLE_TYPES_CLASS_NAME );
|
|
||||||
// }
|
|
||||||
// catch ( ClassNotFoundException cnfe ) {
|
|
||||||
// try {
|
|
||||||
// oracleTypesClass = ReflectHelper.classForName( DEPRECATED_ORACLE_TYPES_CLASS_NAME );
|
|
||||||
// }
|
|
||||||
// catch ( ClassNotFoundException e ) {
|
|
||||||
// throw new HibernateException( "Unable to locate OracleTypes class", e );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// return oracleTypesClass.getField( "CURSOR" ).getInt( null );
|
|
||||||
// }
|
|
||||||
// catch ( Exception se ) {
|
|
||||||
// throw new HibernateException( "Unable to access OracleTypes.CURSOR value", se );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateError;
|
||||||
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
|
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following class provides some convenience methods for accessing JdbcType instance,
|
||||||
|
* that are loaded into the app class loader, where they have access to the JDBC driver classes.
|
||||||
|
*
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public final class PgJdbcHelper {
|
||||||
|
|
||||||
|
public static boolean isUsable(ServiceRegistry serviceRegistry) {
|
||||||
|
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||||
|
try {
|
||||||
|
classLoaderService.classForName( "org.postgresql.util.PGobject" );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (ClassLoadingException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JdbcType getStructJdbcType(ServiceRegistry serviceRegistry) {
|
||||||
|
return createJdbcType( serviceRegistry, "org.hibernate.dialect.PostgreSQLStructPGObjectJdbcType" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JdbcType getIntervalJdbcType(ServiceRegistry serviceRegistry) {
|
||||||
|
return createJdbcType( serviceRegistry, "org.hibernate.dialect.PostgreSQLIntervalSecondJdbcType" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JdbcType getInetJdbcType(ServiceRegistry serviceRegistry) {
|
||||||
|
return createJdbcType( serviceRegistry, "org.hibernate.dialect.PostgreSQLInetJdbcType" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JdbcType getJsonJdbcType(ServiceRegistry serviceRegistry) {
|
||||||
|
return createJdbcType( serviceRegistry, "org.hibernate.dialect.PostgreSQLJsonPGObjectJsonType" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JdbcType getJsonbJdbcType(ServiceRegistry serviceRegistry) {
|
||||||
|
return createJdbcType( serviceRegistry, "org.hibernate.dialect.PostgreSQLJsonPGObjectJsonbType" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JdbcType createJdbcType(ServiceRegistry serviceRegistry, String className) {
|
||||||
|
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||||
|
try {
|
||||||
|
final Class<?> clazz = classLoaderService.classForName( className );
|
||||||
|
final Constructor<?> constructor = clazz.getConstructor();
|
||||||
|
return (JdbcType) constructor.newInstance();
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException e) {
|
||||||
|
throw new HibernateError( "Class does not have an empty constructor", e );
|
||||||
|
}
|
||||||
|
catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||||
|
throw new HibernateError( "Could not construct JdbcType", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1337,16 +1337,16 @@ public class PostgreSQLDialect extends Dialect {
|
||||||
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
||||||
// HHH-9562
|
// HHH-9562
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||||
if ( PostgreSQLPGObjectJdbcType.isUsable() ) {
|
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLInetJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getInetJdbcType( serviceRegistry ) );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLIntervalSecondJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getIntervalJdbcType( serviceRegistry ) );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLStructJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getStructJdbcType( serviceRegistry ) );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLJsonbJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PgJdbcHelper.getJsonbJdbcType( serviceRegistry ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingInetJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingInetJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingStructJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLStructCastingJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingJsonJdbcType.JSONB_INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingJsonJdbcType.JSONB_INSTANCE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1354,7 +1354,7 @@ public class PostgreSQLDialect extends Dialect {
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingInetJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingInetJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingIntervalSecondJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingStructJdbcType.INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLStructCastingJdbcType.INSTANCE );
|
||||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingJsonJdbcType.JSONB_INSTANCE );
|
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLCastingJsonJdbcType.JSONB_INSTANCE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,22 +6,45 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
|
import java.sql.CallableStatement;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.type.SqlTypes;
|
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.WrapperOptions;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
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 org.postgresql.util.PGobject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christian Beikov
|
* @author Christian Beikov
|
||||||
*/
|
*/
|
||||||
public class PostgreSQLInetJdbcType extends PostgreSQLPGObjectJdbcType {
|
public class PostgreSQLInetJdbcType implements JdbcType {
|
||||||
|
|
||||||
public static final PostgreSQLInetJdbcType INSTANCE = new PostgreSQLInetJdbcType();
|
@Override
|
||||||
|
public int getJdbcTypeCode() {
|
||||||
public PostgreSQLInetJdbcType() {
|
return Types.OTHER;
|
||||||
super( "inet", SqlTypes.INET );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public int getDefaultSqlTypeCode() {
|
||||||
|
return SqlTypes.INET;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
|
||||||
|
// No literal support for now
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
protected <X> X fromString(String string, JavaType<X> javaType, WrapperOptions options) {
|
protected <X> X fromString(String string, JavaType<X> javaType, WrapperOptions options) {
|
||||||
final String host;
|
final String host;
|
||||||
if ( string == null ) {
|
if ( string == null ) {
|
||||||
|
@ -39,4 +62,61 @@ public class PostgreSQLInetJdbcType extends PostgreSQLPGObjectJdbcType {
|
||||||
}
|
}
|
||||||
return javaType.wrap( host, options );
|
return javaType.wrap( host, options );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected <X> String toString(X value, JavaType<X> javaType, WrapperOptions options) {
|
||||||
|
return javaType.unwrap( value, String.class, options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 stringValue = PostgreSQLInetJdbcType.this.toString( value, getJavaType(), options );
|
||||||
|
final PGobject holder = new PGobject();
|
||||||
|
holder.setType( "inet" );
|
||||||
|
holder.setValue( stringValue );
|
||||||
|
st.setObject( index, holder );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||||
|
throws SQLException {
|
||||||
|
final String stringValue = PostgreSQLInetJdbcType.this.toString( value, getJavaType(), options );
|
||||||
|
final PGobject holder = new PGobject();
|
||||||
|
holder.setType( "inet" );
|
||||||
|
holder.setValue( stringValue );
|
||||||
|
st.setObject( name, holder );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@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.getObject( paramIndex ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||||
|
return getObject( statement.getObject( index ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
|
||||||
|
throws SQLException {
|
||||||
|
return getObject( statement.getObject( name ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
private X getObject(Object object, WrapperOptions options) throws SQLException {
|
||||||
|
if ( object == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return fromString( object.toString(), getJavaType(), options );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.sql.CallableStatement;
|
import java.sql.CallableStatement;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
|
@ -16,8 +13,6 @@ import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
|
||||||
import org.hibernate.type.SqlTypes;
|
import org.hibernate.type.SqlTypes;
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
|
@ -30,62 +25,16 @@ import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||||
|
|
||||||
|
import org.postgresql.util.PGInterval;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christian Beikov
|
* @author Christian Beikov
|
||||||
*/
|
*/
|
||||||
public class PostgreSQLIntervalSecondJdbcType implements AdjustableJdbcType {
|
public class PostgreSQLIntervalSecondJdbcType implements AdjustableJdbcType {
|
||||||
|
|
||||||
public static final PostgreSQLIntervalSecondJdbcType INSTANCE = new PostgreSQLIntervalSecondJdbcType();
|
|
||||||
private static final Class<?> PG_INTERVAL_CLASS;
|
|
||||||
private static final Constructor<Object> PG_INTERVAL_CONSTRUCTOR;
|
|
||||||
private static final Method PG_INTERVAL_GET_DAYS;
|
|
||||||
private static final Method PG_INTERVAL_GET_HOURS;
|
|
||||||
private static final Method PG_INTERVAL_GET_MINUTES;
|
|
||||||
private static final Method PG_INTERVAL_GET_SECONDS;
|
|
||||||
private static final Method PG_INTERVAL_GET_MICRO_SECONDS;
|
|
||||||
private static final long SECONDS_PER_DAY = 86400;
|
private static final long SECONDS_PER_DAY = 86400;
|
||||||
private static final long SECONDS_PER_HOUR = 3600;
|
private static final long SECONDS_PER_HOUR = 3600;
|
||||||
private static final long SECONDS_PER_MINUTE = 60;
|
private static final long SECONDS_PER_MINUTE = 60;
|
||||||
|
|
||||||
static {
|
|
||||||
Constructor<Object> constructor;
|
|
||||||
Class<?> pgIntervalClass;
|
|
||||||
Method pgIntervalGetDays;
|
|
||||||
Method pgIntervalGetHours;
|
|
||||||
Method pgIntervalGetMinutes;
|
|
||||||
Method pgIntervalGetSeconds;
|
|
||||||
Method pgIntervalGetMicroSeconds;
|
|
||||||
try {
|
|
||||||
pgIntervalClass = ReflectHelper.classForName(
|
|
||||||
"org.postgresql.util.PGInterval",
|
|
||||||
PostgreSQLIntervalSecondJdbcType.class
|
|
||||||
);
|
|
||||||
constructor = (Constructor<Object>) pgIntervalClass.getConstructor(
|
|
||||||
int.class,
|
|
||||||
int.class,
|
|
||||||
int.class,
|
|
||||||
int.class,
|
|
||||||
int.class,
|
|
||||||
double.class
|
|
||||||
);
|
|
||||||
pgIntervalGetDays = pgIntervalClass.getDeclaredMethod( "getDays" );
|
|
||||||
pgIntervalGetHours = pgIntervalClass.getDeclaredMethod( "getHours" );
|
|
||||||
pgIntervalGetMinutes = pgIntervalClass.getDeclaredMethod( "getMinutes" );
|
|
||||||
pgIntervalGetSeconds = pgIntervalClass.getDeclaredMethod( "getWholeSeconds" );
|
|
||||||
pgIntervalGetMicroSeconds = pgIntervalClass.getDeclaredMethod( "getMicroSeconds" );
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new RuntimeException( "Could not initialize PostgreSQLPGObjectJdbcType", e );
|
|
||||||
}
|
|
||||||
PG_INTERVAL_CLASS = pgIntervalClass;
|
|
||||||
PG_INTERVAL_CONSTRUCTOR = constructor;
|
|
||||||
PG_INTERVAL_GET_DAYS = pgIntervalGetDays;
|
|
||||||
PG_INTERVAL_GET_HOURS = pgIntervalGetHours;
|
|
||||||
PG_INTERVAL_GET_MINUTES = pgIntervalGetMinutes;
|
|
||||||
PG_INTERVAL_GET_SECONDS = pgIntervalGetSeconds;
|
|
||||||
PG_INTERVAL_GET_MICRO_SECONDS = pgIntervalGetMicroSeconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getJdbcTypeCode() {
|
public int getJdbcTypeCode() {
|
||||||
return Types.OTHER;
|
return Types.OTHER;
|
||||||
|
@ -161,19 +110,14 @@ public class PostgreSQLIntervalSecondJdbcType implements AdjustableJdbcType {
|
||||||
double seconds = ( (double) ( secondsLong - minutesLong * 60 ) )
|
double seconds = ( (double) ( secondsLong - minutesLong * 60 ) )
|
||||||
+ ( (double) d.getNano() ) / 1_000_000_000d;
|
+ ( (double) d.getNano() ) / 1_000_000_000d;
|
||||||
|
|
||||||
try {
|
return new PGInterval(
|
||||||
return PG_INTERVAL_CONSTRUCTOR.newInstance(
|
0,// years
|
||||||
0,// years
|
0, // months
|
||||||
0, // months
|
days,
|
||||||
days,
|
hours,
|
||||||
hours,
|
minutes,
|
||||||
minutes,
|
seconds
|
||||||
seconds
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
|
||||||
throw new IllegalArgumentException( e );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -198,19 +142,15 @@ public class PostgreSQLIntervalSecondJdbcType implements AdjustableJdbcType {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getValue(Object value) {
|
private Object getValue(Object value) {
|
||||||
if ( PG_INTERVAL_CLASS.isInstance( value ) ) {
|
if ( value instanceof PGInterval ) {
|
||||||
try {
|
final PGInterval interval = (PGInterval) value;
|
||||||
final long seconds = (int) PG_INTERVAL_GET_SECONDS.invoke( value )
|
final long seconds = ( (long) interval.getSeconds() )
|
||||||
+ SECONDS_PER_DAY * (int) PG_INTERVAL_GET_DAYS.invoke( value )
|
+ SECONDS_PER_DAY * ( (long) interval.getDays() )
|
||||||
+ SECONDS_PER_HOUR * (int) PG_INTERVAL_GET_HOURS.invoke( value )
|
+ SECONDS_PER_HOUR * ( (long) interval.getHours() )
|
||||||
+ SECONDS_PER_MINUTE * (int) PG_INTERVAL_GET_MINUTES.invoke( value );
|
+ SECONDS_PER_MINUTE * ( (long) interval.getMinutes() );
|
||||||
final long nanos = 1000L * (int) PG_INTERVAL_GET_MICRO_SECONDS.invoke( value );
|
final long nanos = 1000L * ( (long) interval.getMicroSeconds() );
|
||||||
|
|
||||||
return Duration.ofSeconds( seconds, nanos );
|
return Duration.ofSeconds( seconds, nanos );
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new HibernateException( "Couldn't create Duration from interval", e );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,12 @@ import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||||
/**
|
/**
|
||||||
* @author Christian Beikov
|
* @author Christian Beikov
|
||||||
*/
|
*/
|
||||||
public class PostgreSQLJsonbJdbcType extends AbstractPostgreSQLJsonJdbcType {
|
public class PostgreSQLJsonPGObjectJsonType extends AbstractPostgreSQLJsonPGObjectType {
|
||||||
|
public PostgreSQLJsonPGObjectJsonType() {
|
||||||
public static final PostgreSQLJsonbJdbcType INSTANCE = new PostgreSQLJsonbJdbcType( null );
|
this( null, false );
|
||||||
|
}
|
||||||
public PostgreSQLJsonbJdbcType(EmbeddableMappingType embeddableMappingType) {
|
private PostgreSQLJsonPGObjectJsonType(EmbeddableMappingType embeddableMappingType, boolean jsonb) {
|
||||||
super( embeddableMappingType, "jsonb" );
|
super( embeddableMappingType, jsonb );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,6 +26,6 @@ public class PostgreSQLJsonbJdbcType extends AbstractPostgreSQLJsonJdbcType {
|
||||||
EmbeddableMappingType mappingType,
|
EmbeddableMappingType mappingType,
|
||||||
String sqlType,
|
String sqlType,
|
||||||
RuntimeModelCreationContext creationContext) {
|
RuntimeModelCreationContext creationContext) {
|
||||||
return new PostgreSQLJsonbJdbcType( mappingType );
|
return new PostgreSQLJsonPGObjectJsonType( mappingType, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,12 +13,13 @@ import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||||
/**
|
/**
|
||||||
* @author Christian Beikov
|
* @author Christian Beikov
|
||||||
*/
|
*/
|
||||||
public class PostgreSQLJsonJdbcType extends AbstractPostgreSQLJsonJdbcType {
|
public class PostgreSQLJsonPGObjectJsonbType extends AbstractPostgreSQLJsonPGObjectType {
|
||||||
|
|
||||||
public static final PostgreSQLJsonJdbcType INSTANCE = new PostgreSQLJsonJdbcType( null );
|
public PostgreSQLJsonPGObjectJsonbType() {
|
||||||
|
this( null, true );
|
||||||
private PostgreSQLJsonJdbcType(EmbeddableMappingType embeddableMappingType) {
|
}
|
||||||
super( embeddableMappingType, "json" );
|
protected PostgreSQLJsonPGObjectJsonbType(EmbeddableMappingType embeddableMappingType, boolean jsonb) {
|
||||||
|
super( embeddableMappingType, jsonb );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,7 +27,6 @@ public class PostgreSQLJsonJdbcType extends AbstractPostgreSQLJsonJdbcType {
|
||||||
EmbeddableMappingType mappingType,
|
EmbeddableMappingType mappingType,
|
||||||
String sqlType,
|
String sqlType,
|
||||||
RuntimeModelCreationContext creationContext) {
|
RuntimeModelCreationContext creationContext) {
|
||||||
return new PostgreSQLJsonJdbcType( mappingType );
|
return new PostgreSQLJsonPGObjectJsonbType( mappingType, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,176 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.sql.CallableStatement;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Types;
|
|
||||||
|
|
||||||
import org.hibernate.internal.CoreLogging;
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Christian Beikov
|
|
||||||
*/
|
|
||||||
public abstract class PostgreSQLPGObjectJdbcType implements JdbcType {
|
|
||||||
|
|
||||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( PostgreSQLPGObjectJdbcType.class );
|
|
||||||
private static final Constructor<Object> PG_OBJECT_CONSTRUCTOR;
|
|
||||||
private static final Method TYPE_SETTER;
|
|
||||||
private static final Method VALUE_SETTER;
|
|
||||||
|
|
||||||
static {
|
|
||||||
Constructor<Object> constructor = null;
|
|
||||||
Method typeSetter = null;
|
|
||||||
Method valueSetter = null;
|
|
||||||
try {
|
|
||||||
final Class<?> pgObjectClass = ReflectHelper.classForName(
|
|
||||||
"org.postgresql.util.PGobject",
|
|
||||||
PostgreSQLPGObjectJdbcType.class
|
|
||||||
);
|
|
||||||
//noinspection unchecked
|
|
||||||
constructor = (Constructor<Object>) pgObjectClass.getConstructor();
|
|
||||||
typeSetter = ReflectHelper.setterMethodOrNull( pgObjectClass, "type", String.class );
|
|
||||||
valueSetter = ReflectHelper.setterMethodOrNull( pgObjectClass, "value", String.class );
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
LOG.postgreSQLJdbcDriverNotAccessible();
|
|
||||||
}
|
|
||||||
PG_OBJECT_CONSTRUCTOR = constructor;
|
|
||||||
TYPE_SETTER = typeSetter;
|
|
||||||
VALUE_SETTER = valueSetter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String typeName;
|
|
||||||
private final int sqlTypeCode;
|
|
||||||
|
|
||||||
public PostgreSQLPGObjectJdbcType(String typeName, int sqlTypeCode) {
|
|
||||||
this.typeName = typeName;
|
|
||||||
this.sqlTypeCode = sqlTypeCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isUsable() {
|
|
||||||
return PG_OBJECT_CONSTRUCTOR != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getJdbcTypeCode() {
|
|
||||||
return Types.OTHER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getDefaultSqlTypeCode() {
|
|
||||||
return sqlTypeCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTypeName() {
|
|
||||||
return typeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <X> X fromString(String string, JavaType<X> javaType, WrapperOptions options) throws SQLException {
|
|
||||||
return javaType.wrap( string, options );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <X> String toString(X value, JavaType<X> javaType, WrapperOptions options) {
|
|
||||||
return javaType.unwrap( value, String.class, options );
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 stringValue = ( (PostgreSQLPGObjectJdbcType) getJdbcType() ).toString(
|
|
||||||
value,
|
|
||||||
getJavaType(),
|
|
||||||
options
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
Object holder = PG_OBJECT_CONSTRUCTOR.newInstance();
|
|
||||||
TYPE_SETTER.invoke( holder, typeName );
|
|
||||||
VALUE_SETTER.invoke( holder, stringValue );
|
|
||||||
st.setObject( index, holder );
|
|
||||||
}
|
|
||||||
catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
|
||||||
throw new IllegalArgumentException( e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
|
||||||
throws SQLException {
|
|
||||||
final String stringValue = ( (PostgreSQLPGObjectJdbcType) getJdbcType() ).toString(
|
|
||||||
value,
|
|
||||||
getJavaType(),
|
|
||||||
options
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
Object holder = PG_OBJECT_CONSTRUCTOR.newInstance();
|
|
||||||
TYPE_SETTER.invoke( holder, typeName );
|
|
||||||
VALUE_SETTER.invoke( holder, stringValue );
|
|
||||||
st.setObject( name, holder );
|
|
||||||
}
|
|
||||||
catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
|
||||||
throw new IllegalArgumentException( e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@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.getObject( paramIndex ), options );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
|
||||||
return getObject( statement.getObject( index ), options );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
|
|
||||||
throws SQLException {
|
|
||||||
return getObject( statement.getObject( name ), options );
|
|
||||||
}
|
|
||||||
|
|
||||||
private X getObject(Object object, WrapperOptions options) throws SQLException {
|
|
||||||
if ( object == null ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return ( (PostgreSQLPGObjectJdbcType) getJdbcType() ).fromString(
|
|
||||||
object.toString(),
|
|
||||||
getJavaType(),
|
|
||||||
options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,11 +23,14 @@ import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||||
/**
|
/**
|
||||||
* @author Christian Beikov
|
* @author Christian Beikov
|
||||||
*/
|
*/
|
||||||
public class PostgreSQLCastingStructJdbcType extends PostgreSQLStructJdbcType {
|
public class PostgreSQLStructCastingJdbcType extends AbstractPostgreSQLStructJdbcType {
|
||||||
|
|
||||||
public static final PostgreSQLCastingStructJdbcType INSTANCE = new PostgreSQLCastingStructJdbcType( null, null, null );
|
public static final PostgreSQLStructCastingJdbcType INSTANCE = new PostgreSQLStructCastingJdbcType();
|
||||||
|
public PostgreSQLStructCastingJdbcType() {
|
||||||
|
this( null, null, null );
|
||||||
|
}
|
||||||
|
|
||||||
public PostgreSQLCastingStructJdbcType(
|
private PostgreSQLStructCastingJdbcType(
|
||||||
EmbeddableMappingType embeddableMappingType,
|
EmbeddableMappingType embeddableMappingType,
|
||||||
String typeName,
|
String typeName,
|
||||||
int[] orderMapping) {
|
int[] orderMapping) {
|
||||||
|
@ -39,7 +42,7 @@ public class PostgreSQLCastingStructJdbcType extends PostgreSQLStructJdbcType {
|
||||||
EmbeddableMappingType mappingType,
|
EmbeddableMappingType mappingType,
|
||||||
String sqlType,
|
String sqlType,
|
||||||
RuntimeModelCreationContext creationContext) {
|
RuntimeModelCreationContext creationContext) {
|
||||||
return new PostgreSQLCastingStructJdbcType(
|
return new PostgreSQLStructCastingJdbcType(
|
||||||
mappingType,
|
mappingType,
|
||||||
sqlType,
|
sqlType,
|
||||||
creationContext.getBootModel()
|
creationContext.getBootModel()
|
||||||
|
@ -68,7 +71,7 @@ public class PostgreSQLCastingStructJdbcType extends PostgreSQLStructJdbcType {
|
||||||
@Override
|
@Override
|
||||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
final String stringValue = ( (PostgreSQLCastingStructJdbcType) getJdbcType() ).toString(
|
final String stringValue = ( (PostgreSQLStructCastingJdbcType) getJdbcType() ).toString(
|
||||||
value,
|
value,
|
||||||
getJavaType(),
|
getJavaType(),
|
||||||
options
|
options
|
||||||
|
@ -79,7 +82,7 @@ public class PostgreSQLCastingStructJdbcType extends PostgreSQLStructJdbcType {
|
||||||
@Override
|
@Override
|
||||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
final String stringValue = ( (PostgreSQLCastingStructJdbcType) getJdbcType() ).toString(
|
final String stringValue = ( (PostgreSQLStructCastingJdbcType) getJdbcType() ).toString(
|
||||||
value,
|
value,
|
||||||
getJavaType(),
|
getJavaType(),
|
||||||
options
|
options
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* 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.SQLException;
|
||||||
|
|
||||||
|
import org.hibernate.boot.model.naming.Identifier;
|
||||||
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
|
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.java.spi.UnknownBasicJavaType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||||
|
|
||||||
|
import org.postgresql.util.PGobject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public class PostgreSQLStructPGObjectJdbcType extends AbstractPostgreSQLStructJdbcType {
|
||||||
|
|
||||||
|
private final ValueExtractor<Object[]> objectArrayExtractor;
|
||||||
|
|
||||||
|
public PostgreSQLStructPGObjectJdbcType() {
|
||||||
|
this( null, null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private PostgreSQLStructPGObjectJdbcType(
|
||||||
|
EmbeddableMappingType embeddableMappingType,
|
||||||
|
String typeName,
|
||||||
|
int[] orderMapping) {
|
||||||
|
super( embeddableMappingType, typeName, orderMapping );
|
||||||
|
this.objectArrayExtractor = super.getExtractor( new UnknownBasicJavaType<>( Object[].class ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AggregateJdbcType resolveAggregateJdbcType(
|
||||||
|
EmbeddableMappingType mappingType,
|
||||||
|
String sqlType,
|
||||||
|
RuntimeModelCreationContext creationContext) {
|
||||||
|
return new PostgreSQLStructPGObjectJdbcType(
|
||||||
|
mappingType,
|
||||||
|
sqlType,
|
||||||
|
creationContext.getBootModel()
|
||||||
|
.getDatabase()
|
||||||
|
.getDefaultNamespace()
|
||||||
|
.locateUserDefinedType( Identifier.toIdentifier( sqlType ) )
|
||||||
|
.getOrderMapping()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 stringValue = ( (AbstractPostgreSQLStructJdbcType) getJdbcType() ).toString(
|
||||||
|
value,
|
||||||
|
getJavaType(),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
final PGobject holder = new PGobject();
|
||||||
|
holder.setType( getTypeName() );
|
||||||
|
holder.setValue( stringValue );
|
||||||
|
st.setObject( index, holder );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||||
|
throws SQLException {
|
||||||
|
final String stringValue = ( (AbstractPostgreSQLStructJdbcType) getJdbcType() ).toString(
|
||||||
|
value,
|
||||||
|
getJavaType(),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
final PGobject holder = new PGobject();
|
||||||
|
holder.setType( getTypeName() );
|
||||||
|
holder.setValue( stringValue );
|
||||||
|
st.setObject( name, holder );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
|
||||||
|
if ( javaType.getJavaTypeClass() == Object[].class ) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (ValueExtractor<X>) objectArrayExtractor;
|
||||||
|
}
|
||||||
|
return super.getExtractor( javaType );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,401 @@
|
||||||
|
/*
|
||||||
|
* 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 java.sql.Struct;
|
||||||
|
|
||||||
|
import org.hibernate.boot.model.naming.Identifier;
|
||||||
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
|
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.java.spi.UnknownBasicJavaType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||||
|
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public class StructJdbcType implements AggregateJdbcType {
|
||||||
|
|
||||||
|
public static final AggregateJdbcType INSTANCE = new StructJdbcType();
|
||||||
|
|
||||||
|
private final String typeName;
|
||||||
|
private final int[] orderMapping;
|
||||||
|
private final int[] inverseOrderMapping;
|
||||||
|
private final EmbeddableMappingType embeddableMappingType;
|
||||||
|
private final ValueExtractor<Object[]> objectArrayExtractor;
|
||||||
|
|
||||||
|
private StructJdbcType() {
|
||||||
|
// The default instance is for reading only and will return an Object[]
|
||||||
|
this( null, null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public StructJdbcType(EmbeddableMappingType embeddableMappingType, String typeName, int[] orderMapping) {
|
||||||
|
this.embeddableMappingType = embeddableMappingType;
|
||||||
|
this.typeName = typeName;
|
||||||
|
this.orderMapping = orderMapping;
|
||||||
|
if ( orderMapping == null ) {
|
||||||
|
this.inverseOrderMapping = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final int[] inverseOrderMapping = new int[orderMapping.length];
|
||||||
|
for ( int i = 0; i < orderMapping.length; i++ ) {
|
||||||
|
inverseOrderMapping[orderMapping[i]] = i;
|
||||||
|
}
|
||||||
|
this.inverseOrderMapping = inverseOrderMapping;
|
||||||
|
}
|
||||||
|
// We cache the extractor for Object[] here
|
||||||
|
// since that is used in AggregateEmbeddableFetchImpl and AggregateEmbeddableResultImpl
|
||||||
|
this.objectArrayExtractor = createBasicExtractor( new UnknownBasicJavaType<>( Object[].class ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getJdbcTypeCode() {
|
||||||
|
return SqlTypes.STRUCT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AggregateJdbcType resolveAggregateJdbcType(
|
||||||
|
EmbeddableMappingType mappingType,
|
||||||
|
String sqlType,
|
||||||
|
RuntimeModelCreationContext creationContext) {
|
||||||
|
return new StructJdbcType(
|
||||||
|
mappingType,
|
||||||
|
sqlType,
|
||||||
|
creationContext.getBootModel()
|
||||||
|
.getDatabase()
|
||||||
|
.getDefaultNamespace()
|
||||||
|
.locateUserDefinedType( Identifier.toIdentifier( sqlType ) )
|
||||||
|
.getOrderMapping()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddableMappingType getEmbeddableMappingType() {
|
||||||
|
return embeddableMappingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> JavaType<T> getJdbcRecommendedJavaTypeMapping(
|
||||||
|
Integer precision,
|
||||||
|
Integer scale,
|
||||||
|
TypeConfiguration typeConfiguration) {
|
||||||
|
if ( embeddableMappingType == null ) {
|
||||||
|
return typeConfiguration.getJavaTypeRegistry().getDescriptor( Object[].class );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (JavaType<T>) embeddableMappingType.getMappedJavaType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerOutParameter(CallableStatement callableStatement, String name) throws SQLException {
|
||||||
|
callableStatement.registerOutParameter( name, getJdbcTypeCode(), typeName );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerOutParameter(CallableStatement callableStatement, int index) throws SQLException {
|
||||||
|
callableStatement.registerOutParameter( index, getJdbcTypeCode(), typeName );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createJdbcValue(Object domainValue, WrapperOptions options) throws SQLException {
|
||||||
|
final Object[] jdbcValues = StructHelper.getJdbcValues(
|
||||||
|
embeddableMappingType,
|
||||||
|
orderMapping,
|
||||||
|
embeddableMappingType.getValues( domainValue ),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
return options.getSession()
|
||||||
|
.getJdbcCoordinator()
|
||||||
|
.getLogicalConnection()
|
||||||
|
.getPhysicalConnection()
|
||||||
|
.createStruct( typeName, jdbcValues );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] extractJdbcValues(Object rawJdbcValue, WrapperOptions options) throws SQLException {
|
||||||
|
final Object[] attributes = ( (Struct) rawJdbcValue ).getAttributes();
|
||||||
|
wrapRawJdbcValues( embeddableMappingType, orderMapping, inverseOrderMapping, attributes, 0, options );
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 {
|
||||||
|
st.setObject( index, createJdbcValue( value, options ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||||
|
throws SQLException {
|
||||||
|
st.setObject( name, createJdbcValue( value, options ) );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
|
||||||
|
if ( javaType.getJavaTypeClass() == Object[].class ) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (ValueExtractor<X>) objectArrayExtractor;
|
||||||
|
}
|
||||||
|
return createBasicExtractor( javaType );
|
||||||
|
}
|
||||||
|
|
||||||
|
private <X> BasicExtractor<X> createBasicExtractor(JavaType<X> javaType) {
|
||||||
|
return new BasicExtractor<>( javaType, this ) {
|
||||||
|
@Override
|
||||||
|
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||||
|
return getValue( rs.getObject( paramIndex ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||||
|
return getValue( statement.getObject( index ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
|
||||||
|
throws SQLException {
|
||||||
|
return getValue( statement.getObject( name ), options );
|
||||||
|
}
|
||||||
|
|
||||||
|
private X getValue(Object object, WrapperOptions options) throws SQLException {
|
||||||
|
if ( object == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final Struct struct = (Struct) object;
|
||||||
|
final Object[] values = struct.getAttributes();
|
||||||
|
final boolean jdbcRepresentation = getJavaType().getJavaTypeClass() == Object[].class;
|
||||||
|
if ( jdbcRepresentation ) {
|
||||||
|
wrapRawJdbcValues( embeddableMappingType, orderMapping, inverseOrderMapping, values, 0, options );
|
||||||
|
//noinspection unchecked
|
||||||
|
return (X) values;
|
||||||
|
}
|
||||||
|
assert embeddableMappingType != null && embeddableMappingType.getJavaType() == getJavaType();
|
||||||
|
final Object[] attributeValues = getAttributeValues(
|
||||||
|
embeddableMappingType,
|
||||||
|
orderMapping,
|
||||||
|
values,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
//noinspection unchecked
|
||||||
|
return (X) embeddableMappingType.getRepresentationStrategy().getInstantiator().instantiate(
|
||||||
|
() -> attributeValues,
|
||||||
|
options.getSessionFactory()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object[] getAttributeValues(
|
||||||
|
EmbeddableMappingType embeddableMappingType,
|
||||||
|
int[] orderMapping,
|
||||||
|
Object[] rawJdbcValues,
|
||||||
|
WrapperOptions options) throws SQLException {
|
||||||
|
final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();
|
||||||
|
final Object[] attributeValues;
|
||||||
|
if ( numberOfAttributeMappings != rawJdbcValues.length || orderMapping != null ) {
|
||||||
|
attributeValues = new Object[numberOfAttributeMappings];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
attributeValues = rawJdbcValues;
|
||||||
|
}
|
||||||
|
int jdbcIndex = 0;
|
||||||
|
for ( int i = 0; i < numberOfAttributeMappings; i++ ) {
|
||||||
|
final int attributeIndex;
|
||||||
|
if ( orderMapping == null ) {
|
||||||
|
attributeIndex = i;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
attributeIndex = orderMapping[i];
|
||||||
|
}
|
||||||
|
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( attributeIndex );
|
||||||
|
jdbcIndex += injectAttributeValue(
|
||||||
|
attributeMapping,
|
||||||
|
attributeValues,
|
||||||
|
attributeIndex,
|
||||||
|
rawJdbcValues,
|
||||||
|
jdbcIndex,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return attributeValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int injectAttributeValue(
|
||||||
|
AttributeMapping attributeMapping,
|
||||||
|
Object[] attributeValues,
|
||||||
|
int attributeIndex,
|
||||||
|
Object[] rawJdbcValues,
|
||||||
|
int jdbcIndex,
|
||||||
|
WrapperOptions options) throws SQLException {
|
||||||
|
final MappingType mappedType = attributeMapping.getMappedType();
|
||||||
|
final int jdbcValueCount;
|
||||||
|
final Object rawJdbcValue = rawJdbcValues[jdbcIndex];
|
||||||
|
if ( mappedType instanceof EmbeddableMappingType ) {
|
||||||
|
final EmbeddableMappingType embeddableMappingType = (EmbeddableMappingType) mappedType;
|
||||||
|
if ( embeddableMappingType.getAggregateMapping() != null ) {
|
||||||
|
jdbcValueCount = 1;
|
||||||
|
if ( rawJdbcValue == null ) {
|
||||||
|
attributeValues[attributeIndex] = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final AggregateJdbcType aggregateJdbcType = (AggregateJdbcType) embeddableMappingType.getAggregateMapping()
|
||||||
|
.getJdbcMapping()
|
||||||
|
.getJdbcType();
|
||||||
|
final Object[] subValues;
|
||||||
|
if ( aggregateJdbcType instanceof StructJdbcType ) {
|
||||||
|
subValues = getAttributeValues(
|
||||||
|
embeddableMappingType,
|
||||||
|
( (StructJdbcType) aggregateJdbcType ).orderMapping,
|
||||||
|
( (Struct) rawJdbcValue ).getAttributes(),
|
||||||
|
options
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
subValues = aggregateJdbcType.extractJdbcValues( rawJdbcValue, options );
|
||||||
|
}
|
||||||
|
attributeValues[attributeIndex] = embeddableMappingType.getRepresentationStrategy()
|
||||||
|
.getInstantiator()
|
||||||
|
.instantiate(
|
||||||
|
() -> subValues,
|
||||||
|
embeddableMappingType.findContainingEntityMapping()
|
||||||
|
.getEntityPersister()
|
||||||
|
.getFactory()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jdbcValueCount = embeddableMappingType.getJdbcValueCount();
|
||||||
|
final Object[] jdbcValues = new Object[jdbcValueCount];
|
||||||
|
System.arraycopy( rawJdbcValues, jdbcIndex, jdbcValues, 0, jdbcValues.length );
|
||||||
|
final Object[] subValues = getAttributeValues( embeddableMappingType, null, jdbcValues, options );
|
||||||
|
attributeValues[attributeIndex] = embeddableMappingType.getRepresentationStrategy()
|
||||||
|
.getInstantiator()
|
||||||
|
.instantiate(
|
||||||
|
() -> subValues,
|
||||||
|
embeddableMappingType.findContainingEntityMapping()
|
||||||
|
.getEntityPersister()
|
||||||
|
.getFactory()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert attributeMapping.getJdbcTypeCount() == 1;
|
||||||
|
jdbcValueCount = 1;
|
||||||
|
final JdbcMapping jdbcMapping = attributeMapping.getSingleJdbcMapping();
|
||||||
|
final Object jdbcValue;
|
||||||
|
if ( rawJdbcValue == null ) {
|
||||||
|
jdbcValue = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) {
|
||||||
|
case SqlTypes.TIMESTAMP_WITH_TIMEZONE:
|
||||||
|
case SqlTypes.TIMESTAMP_UTC:
|
||||||
|
// Only transform the raw jdbc value if it could be a TIMESTAMPTZ
|
||||||
|
jdbcValue = jdbcMapping.getJdbcJavaType()
|
||||||
|
.wrap( transformRawJdbcValue( rawJdbcValue, options ), options );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
jdbcValue = jdbcMapping.getJdbcJavaType().wrap( rawJdbcValue, options );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attributeValues[attributeIndex] = jdbcMapping.convertToDomainValue( jdbcValue );
|
||||||
|
}
|
||||||
|
return jdbcValueCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int wrapRawJdbcValues(
|
||||||
|
EmbeddableMappingType embeddableMappingType,
|
||||||
|
int[] orderMapping,
|
||||||
|
int[] inverseOrderMapping,
|
||||||
|
Object[] jdbcValues,
|
||||||
|
int jdbcIndex,
|
||||||
|
WrapperOptions options) throws SQLException {
|
||||||
|
final Object[] targetJdbcValues;
|
||||||
|
if ( orderMapping == null ) {
|
||||||
|
targetJdbcValues = jdbcValues;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
targetJdbcValues = jdbcValues.clone();
|
||||||
|
}
|
||||||
|
final int numberOfAttributeMappings = embeddableMappingType.getNumberOfAttributeMappings();
|
||||||
|
for ( int i = 0; i < numberOfAttributeMappings; i++ ) {
|
||||||
|
final AttributeMapping attributeMapping;
|
||||||
|
if ( orderMapping == null ) {
|
||||||
|
attributeMapping = embeddableMappingType.getAttributeMapping( i );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
attributeMapping = embeddableMappingType.getAttributeMapping( orderMapping[i] );
|
||||||
|
}
|
||||||
|
final MappingType mappedType = attributeMapping.getMappedType();
|
||||||
|
|
||||||
|
if ( mappedType instanceof EmbeddableMappingType ) {
|
||||||
|
final EmbeddableMappingType embeddableType = (EmbeddableMappingType) mappedType;
|
||||||
|
if ( embeddableType.getAggregateMapping() != null ) {
|
||||||
|
final AggregateJdbcType aggregateJdbcType = (AggregateJdbcType) embeddableType.getAggregateMapping()
|
||||||
|
.getJdbcMapping()
|
||||||
|
.getJdbcType();
|
||||||
|
final Object rawJdbcValue = targetJdbcValues[jdbcIndex];
|
||||||
|
targetJdbcValues[jdbcIndex] = aggregateJdbcType.extractJdbcValues( rawJdbcValue, options );
|
||||||
|
jdbcIndex++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jdbcIndex = wrapRawJdbcValues( embeddableType, null, null, targetJdbcValues, jdbcIndex, options );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert attributeMapping.getJdbcTypeCount() == 1;
|
||||||
|
final Object rawJdbcValue = targetJdbcValues[jdbcIndex];
|
||||||
|
if ( rawJdbcValue != null ) {
|
||||||
|
final JdbcMapping jdbcMapping = attributeMapping.getSingleJdbcMapping();
|
||||||
|
switch ( jdbcMapping.getJdbcType().getDefaultSqlTypeCode() ) {
|
||||||
|
case SqlTypes.TIMESTAMP_WITH_TIMEZONE:
|
||||||
|
case SqlTypes.TIMESTAMP_UTC:
|
||||||
|
// Only transform the raw jdbc value if it could be a TIMESTAMPTZ
|
||||||
|
targetJdbcValues[jdbcIndex] = jdbcMapping.getJdbcJavaType()
|
||||||
|
.wrap( transformRawJdbcValue( rawJdbcValue, options ), options );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
targetJdbcValues[jdbcIndex] = jdbcMapping.getJdbcJavaType().wrap( rawJdbcValue, options );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jdbcIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( orderMapping != null ) {
|
||||||
|
StructHelper.orderJdbcValues( embeddableMappingType, inverseOrderMapping, targetJdbcValues, jdbcValues );
|
||||||
|
}
|
||||||
|
return jdbcIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object transformRawJdbcValue(Object rawJdbcValue, WrapperOptions options) {
|
||||||
|
return rawJdbcValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ package org.hibernate.procedure.internal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.dialect.PostgreSQLStructJdbcType;
|
import org.hibernate.dialect.AbstractPostgreSQLStructJdbcType;
|
||||||
import org.hibernate.procedure.spi.FunctionReturnImplementor;
|
import org.hibernate.procedure.spi.FunctionReturnImplementor;
|
||||||
import org.hibernate.procedure.spi.ProcedureCallImplementor;
|
import org.hibernate.procedure.spi.ProcedureCallImplementor;
|
||||||
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
|
import org.hibernate.procedure.spi.ProcedureParameterImplementor;
|
||||||
|
@ -156,9 +156,9 @@ public class PostgreSQLCallableStatementSupport extends AbstractStandardCallable
|
||||||
);
|
);
|
||||||
final OutputableType<?> type = registration.getParameterType();
|
final OutputableType<?> type = registration.getParameterType();
|
||||||
final String castType;
|
final String castType;
|
||||||
if ( type != null && type.getJdbcType() instanceof PostgreSQLStructJdbcType ) {
|
if ( type != null && type.getJdbcType() instanceof AbstractPostgreSQLStructJdbcType ) {
|
||||||
// We have to cast struct type parameters so that PostgreSQL understands nulls
|
// We have to cast struct type parameters so that PostgreSQL understands nulls
|
||||||
castType = ( (PostgreSQLStructJdbcType) type.getJdbcType() ).getTypeName();
|
castType = ( (AbstractPostgreSQLStructJdbcType) type.getJdbcType() ).getTypeName();
|
||||||
buffer.append( "cast(" );
|
buffer.append( "cast(" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -37,19 +37,6 @@ import org.hibernate.type.spi.TypeConfiguration;
|
||||||
public class ArrayJdbcType implements JdbcType {
|
public class ArrayJdbcType implements JdbcType {
|
||||||
|
|
||||||
public static final ArrayJdbcType INSTANCE = new ArrayJdbcType( ObjectJdbcType.INSTANCE );
|
public static final ArrayJdbcType INSTANCE = new ArrayJdbcType( ObjectJdbcType.INSTANCE );
|
||||||
private static final ClassValue<Method> NAME_BINDER = new ClassValue<>() {
|
|
||||||
@Override
|
|
||||||
protected Method computeValue(Class<?> type) {
|
|
||||||
try {
|
|
||||||
return type.getMethod( "setArray", String.class, java.sql.Array.class );
|
|
||||||
}
|
|
||||||
catch ( Exception ex ) {
|
|
||||||
// add logging? Did we get NoSuchMethodException or SecurityException?
|
|
||||||
// Doesn't matter which. We can't use it.
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final JdbcType elementJdbcType;
|
private final JdbcType elementJdbcType;
|
||||||
|
|
||||||
|
@ -126,25 +113,11 @@ public class ArrayJdbcType implements JdbcType {
|
||||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
final java.sql.Array arr = getArray( value, containerJavaType, options );
|
final java.sql.Array arr = getArray( value, containerJavaType, options );
|
||||||
final Method nameBinder = NAME_BINDER.get( st.getClass() );
|
|
||||||
if ( nameBinder == null ) {
|
|
||||||
try {
|
|
||||||
st.setObject( name, arr, java.sql.Types.ARRAY );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (SQLException ex) {
|
|
||||||
throw new HibernateException( "JDBC driver does not support named parameters for setArray. Use positional.", ex );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Note that it's supposed to have setArray(String,Array) by standard.
|
|
||||||
// There are numerous missing methods that only have versions for positional parameter,
|
|
||||||
// but not named ones.
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
nameBinder.invoke( st, name, arr );
|
st.setObject( name, arr, java.sql.Types.ARRAY );
|
||||||
}
|
}
|
||||||
catch ( Throwable t ) {
|
catch (SQLException ex) {
|
||||||
throw new HibernateException( t );
|
throw new HibernateException( "JDBC driver does not support named parameters for setArray. Use positional.", ex );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.orm.test.id.usertype.inet;
|
package org.hibernate.orm.test.id.usertype.inet;
|
||||||
|
|
||||||
import org.hibernate.dialect.PostgreSQLInetJdbcType;
|
import org.hibernate.dialect.PostgreSQLInetJdbcType;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
import org.hibernate.type.descriptor.java.BasicJavaType;
|
import org.hibernate.type.descriptor.java.BasicJavaType;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.id.usertype.json;
|
package org.hibernate.orm.test.id.usertype.json;
|
||||||
|
|
||||||
import org.hibernate.dialect.PostgreSQLJsonbJdbcType;
|
import org.hibernate.dialect.PostgreSQLJsonPGObjectJsonbType;
|
||||||
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
|
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
|
||||||
|
|
||||||
public class JsonType extends AbstractSingleColumnStandardBasicType<Json> {
|
public class JsonType extends AbstractSingleColumnStandardBasicType<Json> {
|
||||||
|
@ -14,7 +14,7 @@ public class JsonType extends AbstractSingleColumnStandardBasicType<Json> {
|
||||||
public static final JsonType INSTANCE = new JsonType();
|
public static final JsonType INSTANCE = new JsonType();
|
||||||
|
|
||||||
public JsonType() {
|
public JsonType() {
|
||||||
super( PostgreSQLJsonbJdbcType.INSTANCE, JsonJavaType.INSTANCE );
|
super( new PostgreSQLJsonPGObjectJsonbType(), JsonJavaType.INSTANCE );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,7 +18,7 @@ import org.hibernate.spatial.JTSGeometryJavaType;
|
||||||
*/
|
*/
|
||||||
public interface ContributorImplementor {
|
public interface ContributorImplementor {
|
||||||
|
|
||||||
default void contributeJavaTypes(TypeContributions typeContributions) {
|
default void contributeJavaTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||||
typeContributions.contributeJavaType( GeolatteGeometryJavaType.GEOMETRY_INSTANCE );
|
typeContributions.contributeJavaType( GeolatteGeometryJavaType.GEOMETRY_INSTANCE );
|
||||||
typeContributions.contributeJavaType( GeolatteGeometryJavaType.POINT_INSTANCE );
|
typeContributions.contributeJavaType( GeolatteGeometryJavaType.POINT_INSTANCE );
|
||||||
typeContributions.contributeJavaType( GeolatteGeometryJavaType.LINESTRING_INSTANCE );
|
typeContributions.contributeJavaType( GeolatteGeometryJavaType.LINESTRING_INSTANCE );
|
||||||
|
@ -40,7 +40,7 @@ public interface ContributorImplementor {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void contributeJdbcTypes(TypeContributions typeContributions);
|
void contributeJdbcTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry);
|
||||||
|
|
||||||
void contributeFunctions(FunctionContributions functionContributions);
|
void contributeFunctions(FunctionContributions functionContributions);
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ public class SpatialTypeContributor implements TypeContributor {
|
||||||
ContributorImplementor contributorImplementor = ContributorResolver.resolveSpatialtypeContributorImplementor( serviceRegistry );
|
ContributorImplementor contributorImplementor = ContributorResolver.resolveSpatialtypeContributorImplementor( serviceRegistry );
|
||||||
|
|
||||||
if (contributorImplementor != null) {
|
if (contributorImplementor != null) {
|
||||||
contributorImplementor.contributeJavaTypes( typeContributions );
|
contributorImplementor.contributeJavaTypes( typeContributions, serviceRegistry );
|
||||||
contributorImplementor.contributeJdbcTypes( typeContributions );
|
contributorImplementor.contributeJdbcTypes( typeContributions, serviceRegistry );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ package org.hibernate.spatial.dialect.cockroachdb;
|
||||||
|
|
||||||
import org.hibernate.boot.model.FunctionContributions;
|
import org.hibernate.boot.model.FunctionContributions;
|
||||||
import org.hibernate.boot.model.TypeContributions;
|
import org.hibernate.boot.model.TypeContributions;
|
||||||
import org.hibernate.dialect.PostgreSQLPGObjectJdbcType;
|
import org.hibernate.dialect.PgJdbcHelper;
|
||||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.spatial.FunctionKey;
|
import org.hibernate.spatial.FunctionKey;
|
||||||
|
@ -30,9 +30,9 @@ public class CockroachDbContributor implements ContributorImplementor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contributeJdbcTypes(TypeContributions typeContributions) {
|
public void contributeJdbcTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||||
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
||||||
if ( PostgreSQLPGObjectJdbcType.isUsable() ) {
|
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
typeContributions.contributeJdbcType( PGGeometryJdbcType.INSTANCE_WKB_2 );
|
typeContributions.contributeJdbcType( PGGeometryJdbcType.INSTANCE_WKB_2 );
|
||||||
typeContributions.contributeJdbcType( PGGeographyJdbcType.INSTANCE_WKB_2 );
|
typeContributions.contributeJdbcType( PGGeographyJdbcType.INSTANCE_WKB_2 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class H2GisDialectContributor implements ContributorImplementor {
|
||||||
this.serviceRegistry = serviceRegistry;
|
this.serviceRegistry = serviceRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void contributeJdbcTypes(TypeContributions typeContributions) {
|
public void contributeJdbcTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||||
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
||||||
typeContributions.contributeJdbcType( H2GISGeometryType.INSTANCE );
|
typeContributions.contributeJdbcType( H2GISGeometryType.INSTANCE );
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class MariaDBDialectContributor implements ContributorImplementor {
|
||||||
this.serviceRegistry = serviceRegistry;
|
this.serviceRegistry = serviceRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void contributeJdbcTypes(TypeContributions typeContributions) {
|
public void contributeJdbcTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||||
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
||||||
typeContributions.contributeJdbcType( MySQLGeometryJdbcType.INSTANCE );
|
typeContributions.contributeJdbcType( MySQLGeometryJdbcType.INSTANCE );
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class MySQLDialectContributor implements ContributorImplementor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contributeJdbcTypes(TypeContributions typeContributions) {
|
public void contributeJdbcTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||||
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
||||||
typeContributions.contributeJdbcType( MySQLGeometryJdbcType.INSTANCE);
|
typeContributions.contributeJdbcType( MySQLGeometryJdbcType.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class OracleDialectContributor implements ContributorImplementor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contributeJdbcTypes(TypeContributions typeContributions) {
|
public void contributeJdbcTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||||
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
||||||
final ConfigurationService cfgService = getServiceRegistry().getService( ConfigurationService.class );
|
final ConfigurationService cfgService = getServiceRegistry().getService( ConfigurationService.class );
|
||||||
final StrategySelector strategySelector = getServiceRegistry().getService( StrategySelector.class );
|
final StrategySelector strategySelector = getServiceRegistry().getService( StrategySelector.class );
|
||||||
|
|
|
@ -9,7 +9,7 @@ package org.hibernate.spatial.dialect.postgis;
|
||||||
|
|
||||||
import org.hibernate.boot.model.FunctionContributions;
|
import org.hibernate.boot.model.FunctionContributions;
|
||||||
import org.hibernate.boot.model.TypeContributions;
|
import org.hibernate.boot.model.TypeContributions;
|
||||||
import org.hibernate.dialect.PostgreSQLPGObjectJdbcType;
|
import org.hibernate.dialect.PgJdbcHelper;
|
||||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.spatial.HSMessageLogger;
|
import org.hibernate.spatial.HSMessageLogger;
|
||||||
|
@ -17,16 +17,16 @@ import org.hibernate.spatial.contributor.ContributorImplementor;
|
||||||
|
|
||||||
public class PostgisDialectContributor implements ContributorImplementor {
|
public class PostgisDialectContributor implements ContributorImplementor {
|
||||||
|
|
||||||
private final ServiceRegistry serviceRegistryegistry;
|
private final ServiceRegistry serviceRegistry;
|
||||||
|
|
||||||
public PostgisDialectContributor(ServiceRegistry serviceRegistry) {
|
public PostgisDialectContributor(ServiceRegistry serviceRegistry) {
|
||||||
this.serviceRegistryegistry = serviceRegistry;
|
this.serviceRegistry = serviceRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contributeJdbcTypes(TypeContributions typeContributions) {
|
public void contributeJdbcTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||||
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
||||||
if ( PostgreSQLPGObjectJdbcType.isUsable() ) {
|
if ( PgJdbcHelper.isUsable( serviceRegistry ) ) {
|
||||||
typeContributions.contributeJdbcType( PGGeometryJdbcType.INSTANCE_WKB_2 );
|
typeContributions.contributeJdbcType( PGGeometryJdbcType.INSTANCE_WKB_2 );
|
||||||
typeContributions.contributeJdbcType( PGGeographyJdbcType.INSTANCE_WKB_2 );
|
typeContributions.contributeJdbcType( PGGeographyJdbcType.INSTANCE_WKB_2 );
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,6 @@ public class PostgisDialectContributor implements ContributorImplementor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceRegistry getServiceRegistry() {
|
public ServiceRegistry getServiceRegistry() {
|
||||||
return this.serviceRegistryegistry;
|
return this.serviceRegistry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class SqlServerDialectContributor implements ContributorImplementor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contributeJdbcTypes(TypeContributions typeContributions) {
|
public void contributeJdbcTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||||
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() );
|
||||||
typeContributions.contributeJdbcType( SqlServerGeometryType.INSTANCE );
|
typeContributions.contributeJdbcType( SqlServerGeometryType.INSTANCE );
|
||||||
typeContributions.contributeJdbcType( SqlServerGeographyType.INSTANCE );
|
typeContributions.contributeJdbcType( SqlServerGeographyType.INSTANCE );
|
||||||
|
|
Loading…
Reference in New Issue