HHH-18020 realign behavior of ClobJdbcType with BlobJdbcType

there was some organic divergence here
This commit is contained in:
Gavin King 2024-04-27 14:43:26 +02:00
parent c955150b27
commit 72261fd806
8 changed files with 122 additions and 118 deletions

View File

@ -876,12 +876,7 @@ public class DB2LegacyDialect extends Dialect {
// Therefore here we overwrite the sql type descriptors to
// use the non-N variants which are supported.
jdbcTypeRegistry.addDescriptor( Types.NCHAR, CharJdbcType.INSTANCE );
jdbcTypeRegistry.addDescriptor(
Types.NCLOB,
useInputStreamToInsertBlob()
? ClobJdbcType.STREAM_BINDING
: ClobJdbcType.CLOB_BINDING
);
jdbcTypeRegistry.addDescriptor( Types.NCLOB, ClobJdbcType.STREAM_BINDING );
jdbcTypeRegistry.addDescriptor( Types.NVARCHAR, VarcharJdbcType.INSTANCE );
jdbcTypeRegistry.addDescriptor( Types.NUMERIC, DecimalJdbcType.INSTANCE );

View File

@ -958,12 +958,7 @@ public class DB2Dialect extends Dialect {
// Therefore here we overwrite the sql type descriptors to
// use the non-N variants which are supported.
jdbcTypeRegistry.addDescriptor( Types.NCHAR, CharJdbcType.INSTANCE );
jdbcTypeRegistry.addDescriptor(
Types.NCLOB,
useInputStreamToInsertBlob()
? ClobJdbcType.STREAM_BINDING
: ClobJdbcType.CLOB_BINDING
);
jdbcTypeRegistry.addDescriptor( Types.NCLOB, ClobJdbcType.STREAM_BINDING );
jdbcTypeRegistry.addDescriptor( Types.NVARCHAR, VarcharJdbcType.INSTANCE );
jdbcTypeRegistry.addDescriptor( Types.NUMERIC, DecimalJdbcType.INSTANCE );

View File

@ -1688,13 +1688,6 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
jdbcTypeRegistry.addDescriptor( NClobJdbcType.DEFAULT );
}
if ( useInputStreamToInsertBlob() ) {
jdbcTypeRegistry.addDescriptor(
Types.CLOB,
ClobJdbcType.STREAM_BINDING
);
}
if ( getTimeZoneSupport() == TimeZoneSupport.NATIVE ) {
jdbcTypeRegistry.addDescriptor( TimestampUtcAsOffsetDateTimeJdbcType.INSTANCE );
jdbcTypeRegistry.addDescriptor( TimeUtcAsOffsetTimeJdbcType.INSTANCE );

View File

@ -93,35 +93,32 @@ public abstract class BlobJdbcType implements JdbcType {
return byte[].class;
}
private BlobJdbcType getDescriptor(Object value, WrapperOptions options) {
if ( value instanceof byte[] ) {
// performance shortcut for binding BLOB data in byte[] format
return PRIMITIVE_ARRAY_BINDING;
}
else if ( options.useStreamForLobBinding() ) {
return STREAM_BINDING;
}
else {
return BLOB_BINDING;
}
}
@Override
public <X> BasicBinder<X> getBlobBinder(final JavaType<X> javaType) {
return new BasicBinder<>( javaType, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
BlobJdbcType descriptor = BLOB_BINDING;
if ( value instanceof byte[] ) {
// performance shortcut for binding BLOB data in byte[] format
descriptor = PRIMITIVE_ARRAY_BINDING;
}
else if ( options.useStreamForLobBinding() ) {
descriptor = STREAM_BINDING;
}
descriptor.getBlobBinder( javaType ).doBind( st, value, index, options );
getDescriptor( value, options ).getBlobBinder( javaType ).doBind( st, value, index, options );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
BlobJdbcType descriptor = BLOB_BINDING;
if ( value instanceof byte[] ) {
// performance shortcut for binding BLOB data in byte[] format
descriptor = PRIMITIVE_ARRAY_BINDING;
}
else if ( options.useStreamForLobBinding() ) {
descriptor = STREAM_BINDING;
}
descriptor.getBlobBinder( javaType ).doBind( st, value, name, options );
getDescriptor( value, options ).getBlobBinder( javaType ).doBind( st, value, name, options );
}
};
}
@ -202,22 +199,14 @@ public abstract class BlobJdbcType implements JdbcType {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final BinaryStream binaryStream = javaType.unwrap(
value,
BinaryStream.class,
options
);
final BinaryStream binaryStream = javaType.unwrap( value, BinaryStream.class, options );
st.setBinaryStream( index, binaryStream.getInputStream(), binaryStream.getLength() );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
final BinaryStream binaryStream = javaType.unwrap(
value,
BinaryStream.class,
options
);
final BinaryStream binaryStream = javaType.unwrap( value, BinaryStream.class, options );
st.setBinaryStream( name, binaryStream.getInputStream(), binaryStream.getLength() );
}
};

View File

@ -18,8 +18,6 @@ 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.spi.JdbcTypeRegistry;
import org.hibernate.type.spi.TypeConfiguration;
/**
* Descriptor for {@link Types#CLOB CLOB} handling.
@ -47,11 +45,8 @@ public abstract class ClobJdbcType implements AdjustableJdbcType {
public JdbcType resolveIndicatedType(
JdbcTypeIndicators indicators,
JavaType<?> domainJtd) {
final TypeConfiguration typeConfiguration = indicators.getTypeConfiguration();
final JdbcTypeRegistry jdbcTypeRegistry = typeConfiguration.getJdbcTypeRegistry();
return indicators.isNationalized()
? jdbcTypeRegistry.getDescriptor( indicators.resolveJdbcTypeCode( Types.NCLOB ) )
: jdbcTypeRegistry.getDescriptor( indicators.resolveJdbcTypeCode( Types.CLOB ) );
final int jdbcTypeCode = indicators.resolveJdbcTypeCode( indicators.isNationalized() ? Types.NCLOB : Types.CLOB );
return indicators.getTypeConfiguration().getJdbcTypeRegistry().getDescriptor( jdbcTypeCode );
}
@Override
@ -92,9 +87,20 @@ public abstract class ClobJdbcType implements AdjustableJdbcType {
@Override
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
return options.useStreamForLobBinding() ?
STREAM_BINDING.getPreferredJavaTypeClass( options ) :
CLOB_BINDING.getPreferredJavaTypeClass( options );
return String.class;
}
private ClobJdbcType getDescriptor(Object value, WrapperOptions options) {
if ( value instanceof String ) {
// performance shortcut for binding CLOB data in String format
return STRING_BINDING;
}
else if ( options.useStreamForLobBinding() ) {
return STREAM_BINDING;
}
else {
return CLOB_BINDING;
}
}
@Override
@ -103,23 +109,13 @@ public abstract class ClobJdbcType implements AdjustableJdbcType {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
if ( options.useStreamForLobBinding() ) {
STREAM_BINDING.getClobBinder( javaType ).doBind( st, value, index, options );
}
else {
CLOB_BINDING.getClobBinder( javaType ).doBind( st, value, index, options );
}
getDescriptor( value, options ).getClobBinder( javaType ).doBind( st, value, index, options );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
if ( options.useStreamForLobBinding() ) {
STREAM_BINDING.getClobBinder( javaType ).doBind( st, value, name, options );
}
else {
CLOB_BINDING.getClobBinder( javaType ).doBind( st, value, name, options );
}
getDescriptor( value, options ).getClobBinder( javaType ).doBind( st, value, name, options );
}
};
}
@ -222,11 +218,7 @@ public abstract class ClobJdbcType implements AdjustableJdbcType {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final CharacterStream characterStream = javaType.unwrap(
value,
CharacterStream.class,
options
);
final CharacterStream characterStream = javaType.unwrap( value, CharacterStream.class, options );
st.setCharacterStream( index, characterStream.asReader(), characterStream.getLength() );
}
@ -261,22 +253,14 @@ public abstract class ClobJdbcType implements AdjustableJdbcType {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final CharacterStream characterStream = javaType.unwrap(
value,
CharacterStream.class,
options
);
final CharacterStream characterStream = javaType.unwrap( value, CharacterStream.class, options );
st.setCharacterStream( index, characterStream.asReader(), characterStream.getLength() );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
final CharacterStream characterStream = javaType.unwrap(
value,
CharacterStream.class,
options
);
final CharacterStream characterStream = javaType.unwrap( value, CharacterStream.class, options );
st.setCharacterStream( name, characterStream.asReader(), characterStream.getLength() );
}
};

View File

@ -79,9 +79,20 @@ public abstract class NClobJdbcType implements JdbcType {
@Override
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
return options.useStreamForLobBinding() ?
STREAM_BINDING.getPreferredJavaTypeClass( options ) :
NCLOB_BINDING.getPreferredJavaTypeClass( options );
return String.class;
}
private NClobJdbcType getDescriptor(Object value, WrapperOptions options) {
if ( value instanceof String ) {
// performance shortcut for binding CLOB data in String format
return STRING_BINDING;
}
else if ( options.useStreamForLobBinding() ) {
return STREAM_BINDING;
}
else {
return NCLOB_BINDING;
}
}
@Override
@ -90,23 +101,63 @@ public abstract class NClobJdbcType implements JdbcType {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
if ( options.useStreamForLobBinding() ) {
STREAM_BINDING.getNClobBinder( javaType ).doBind( st, value, index, options );
}
else {
NCLOB_BINDING.getNClobBinder( javaType ).doBind( st, value, index, options );
}
getDescriptor( value, options ).getNClobBinder( javaType ).doBind( st, value, index, options );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
if ( options.useStreamForLobBinding() ) {
STREAM_BINDING.getNClobBinder( javaType ).doBind( st, value, name, options );
}
else {
NCLOB_BINDING.getNClobBinder( javaType ).doBind( st, value, name, options );
}
getDescriptor( value, options ).getNClobBinder( javaType ).doBind( st, value, name, options );
}
};
}
};
public static final NClobJdbcType STRING_BINDING = new NClobJdbcType() {
@Override
public String toString() {
return "NClobTypeDescriptor(STRING_BINDING)";
}
@Override
public Class<?> getPreferredJavaTypeClass(WrapperOptions options) {
return String.class;
}
@Override
public <X> BasicBinder<X> getNClobBinder(final JavaType<X> javaType) {
return new BasicBinder<>( javaType, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
st.setNString( index, javaType.unwrap( value, String.class, options ) );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
st.setNString( name, javaType.unwrap( value, String.class, options ) );
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(final JavaType<X> javaType) {
return new BasicExtractor<>( javaType, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
return javaType.wrap( rs.getNString( paramIndex ), options );
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options)
throws SQLException {
return javaType.wrap( statement.getNString( index ), options );
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
return javaType.wrap( statement.getNString( name ), options );
}
};
}
@ -158,22 +209,14 @@ public abstract class NClobJdbcType implements JdbcType {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final CharacterStream characterStream = javaType.unwrap(
value,
CharacterStream.class,
options
);
final CharacterStream characterStream = javaType.unwrap( value, CharacterStream.class, options );
st.setNCharacterStream( index, characterStream.asReader(), characterStream.getLength() );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
final CharacterStream characterStream = javaType.unwrap(
value,
CharacterStream.class,
options
);
final CharacterStream characterStream = javaType.unwrap( value, CharacterStream.class, options );
st.setNCharacterStream( name, characterStream.asReader(), characterStream.getLength() );
}
};

View File

@ -164,6 +164,9 @@ public class MaterializedNClobBindTest {
throw new IllegalStateException( "PreparedStatement#setNClob unexpectedly called" );
}
}
else if ( "setNString".equals( methodName ) ) {
return null;
}
else {
throw new UnsupportedOperationException( methodName + " is not supported." );

View File

@ -19,6 +19,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.ClobJavaType;
import org.hibernate.type.descriptor.java.StringJavaType;
import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
@ -37,6 +38,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
@BaseUnitTest
public class StringValueMappingTest {
private final StringJavaType stringJavaType = new StringJavaType();
private final ClobJavaType clobJavaType = new ClobJavaType();
private final VarcharJdbcType varcharSqlDescriptor = new VarcharJdbcType();
private final ClobJdbcType clobSqlDescriptor = ClobJdbcType.DEFAULT;
@ -110,33 +112,33 @@ public class StringValueMappingTest {
@Test
public void testNormalClobHandling() throws SQLException {
final ValueExtractor<String> extractor = clobSqlDescriptor.getExtractor( stringJavaType );
final ValueBinder<String> binder = clobSqlDescriptor.getBinder( stringJavaType );
final ValueExtractor<Clob> extractor = clobSqlDescriptor.getExtractor( clobJavaType );
final ValueBinder<Clob> binder = clobSqlDescriptor.getBinder( clobJavaType );
final String fixture = "clob string";
final Clob clob = new StringClobImpl( fixture );
ResultSet resultSet = ResultSetProxy.generateProxy( clob );
final String value = extractor.extract( resultSet, COLUMN_POSITION, wrapperOptions );
assertEquals( fixture, value );
final Clob value = extractor.extract( resultSet, COLUMN_POSITION, wrapperOptions );
assertEquals( clob.length(), value.length() );
PreparedStatement ps = PreparedStatementProxy.generateProxy( clob );
binder.bind( ps, fixture, BIND_POSITION, wrapperOptions );
binder.bind( ps, clob, BIND_POSITION, wrapperOptions );
}
@Test
public void testNullClobHandling() throws SQLException {
final ValueExtractor<String> extractor = clobSqlDescriptor.getExtractor( stringJavaType );
final ValueBinder<String> binder = clobSqlDescriptor.getBinder( stringJavaType );
final ValueExtractor<Clob> extractor = clobSqlDescriptor.getExtractor( clobJavaType );
final ValueBinder<Clob> binder = clobSqlDescriptor.getBinder( clobJavaType );
final String fixture = null;
final Clob clob = null;
ResultSet resultSet = ResultSetProxy.generateProxy( clob );
final String value = extractor.extract( resultSet, COLUMN_POSITION, wrapperOptions );
final Clob value = extractor.extract( resultSet, COLUMN_POSITION, wrapperOptions );
assertNull( value );
PreparedStatement ps = PreparedStatementProxy.generateProxy( clob );
binder.bind( ps, fixture, BIND_POSITION, wrapperOptions );
binder.bind( ps, clob, BIND_POSITION, wrapperOptions );
}
}