HHH-18206 Switch to JDBC LOB APIs for Oracle Dialect (#8486)
HHH-18206 Switch to JDBC LOB APIs for Oracle Dialect
This commit is contained in:
parent
18ec7f178e
commit
ef1cbf589d
|
@ -1045,6 +1045,11 @@ public class CockroachLegacyDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useConnectionToCreateLob() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsOffsetInSubquery() {
|
||||
return true;
|
||||
|
|
|
@ -335,6 +335,11 @@ public class MimerSQLDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useConnectionToCreateLob() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentityColumnSupport getIdentityColumnSupport() {
|
||||
return MimerSQLIdentityColumnSupport.INSTANCE;
|
||||
|
|
|
@ -1563,4 +1563,11 @@ public class OracleLegacyDialect extends Dialect {
|
|||
public boolean supportsFromClauseInUpdate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useInputStreamToInsertBlob() {
|
||||
// see HHH-18206
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -849,6 +849,11 @@ public class PostgreSQLLegacyDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useConnectionToCreateLob() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) {
|
||||
// Workaround for postgres bug #1453
|
||||
|
|
|
@ -138,6 +138,11 @@ public class TeradataDialect extends Dialect {
|
|||
return getVersion().isSameOrAfter( 14 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useConnectionToCreateLob() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxVarcharLength() {
|
||||
//for the unicode server character set
|
||||
|
|
|
@ -1014,6 +1014,11 @@ public class CockroachDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useConnectionToCreateLob() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsOffsetInSubquery() {
|
||||
return true;
|
||||
|
|
|
@ -3647,6 +3647,20 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should BLOB, CLOB, and NCLOB be created solely using respectively
|
||||
* {@link Connection#createBlob()}, {@link Connection#createClob()},
|
||||
* and {@link Connection#createNClob()}.
|
||||
*
|
||||
* @return True if BLOB, CLOB, and NCLOB should be created using JDBC
|
||||
* {@link Connection}.
|
||||
*
|
||||
* @since 6.6
|
||||
*/
|
||||
public boolean useConnectionToCreateLob() {
|
||||
return !useInputStreamToInsertBlob();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this dialect support parameters within the {@code SELECT} clause
|
||||
* of {@code INSERT ... SELECT ...} statements?
|
||||
|
|
|
@ -1041,6 +1041,11 @@ public class DialectDelegateWrapper extends Dialect {
|
|||
return wrapped.useInputStreamToInsertBlob();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useConnectionToCreateLob() {
|
||||
return wrapped.useConnectionToCreateLob();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated(since = "6", forRemoval = true)
|
||||
public boolean supportsParametersInInsertSelect() {
|
||||
|
|
|
@ -1676,4 +1676,11 @@ public class OracleDialect extends Dialect {
|
|||
public String[] getDropEnumTypeCommand(String name) {
|
||||
return new String[] { "drop domain if exists " + name + " force" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useInputStreamToInsertBlob() {
|
||||
// see HHH-18206
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -903,6 +903,11 @@ public class PostgreSQLDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useConnectionToCreateLob() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSelectClauseNullString(int sqlType, TypeConfiguration typeConfiguration) {
|
||||
// TODO: adapt this to handle named enum types!
|
||||
|
|
|
@ -41,7 +41,7 @@ public class NClobProxy extends ClobProxy {
|
|||
* @return The generated proxy.
|
||||
*/
|
||||
public static NClob generateProxy(String string) {
|
||||
return (NClob) Proxy.newProxyInstance( getProxyClassLoader(), PROXY_INTERFACES, new ClobProxy( string ) );
|
||||
return (NClob) Proxy.newProxyInstance( getProxyClassLoader(), PROXY_INTERFACES, new NClobProxy( string ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,7 +53,7 @@ public class NClobProxy extends ClobProxy {
|
|||
* @return The generated proxy.
|
||||
*/
|
||||
public static NClob generateProxy(Reader reader, long length) {
|
||||
return (NClob) Proxy.newProxyInstance( getProxyClassLoader(), PROXY_INTERFACES, new ClobProxy( reader, length ) );
|
||||
return (NClob) Proxy.newProxyInstance( getProxyClassLoader(), PROXY_INTERFACES, new NClobProxy( reader, length ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.type.descriptor;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.LobCreator;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
@ -34,6 +35,13 @@ public interface WrapperOptions {
|
|||
*/
|
||||
SessionFactoryImplementor getSessionFactory();
|
||||
|
||||
/**
|
||||
* Access to the current dialect.
|
||||
*/
|
||||
default Dialect getDialect() {
|
||||
return getSessionFactory().getJdbcServices().getDialect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether streams should be used for binding LOB values.
|
||||
*
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Brett Meyer
|
||||
* @author Loïc Lefèvre
|
||||
*/
|
||||
public class BlobJavaType extends AbstractClassJavaType<Blob> {
|
||||
public static final BlobJavaType INSTANCE = new BlobJavaType();
|
||||
|
@ -133,7 +134,7 @@ public class BlobJavaType extends AbstractClassJavaType<Blob> {
|
|||
else if (Blob.class.isAssignableFrom( type )) {
|
||||
final Blob blob = value instanceof WrappedBlob
|
||||
? ( (WrappedBlob) value ).getWrappedBlob()
|
||||
: value;
|
||||
: getOrCreateBlob(value, options);
|
||||
return (X) blob;
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +145,21 @@ public class BlobJavaType extends AbstractClassJavaType<Blob> {
|
|||
throw unknownUnwrap( type );
|
||||
}
|
||||
|
||||
private Blob getOrCreateBlob(Blob value, WrapperOptions options) throws SQLException {
|
||||
if(options.getDialect().useConnectionToCreateLob()) {
|
||||
if(value.length() == 0) {
|
||||
// empty Blob
|
||||
return options.getLobCreator().createBlob(new byte[0]);
|
||||
}
|
||||
else {
|
||||
return options.getLobCreator().createBlob(value.getBytes(1, (int) value.length()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Blob wrap(X value, WrapperOptions options) {
|
||||
if ( value == null ) {
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.type.descriptor.java;
|
|||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.sql.Clob;
|
||||
import java.sql.NClob;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.hibernate.engine.jdbc.CharacterStream;
|
||||
|
@ -80,6 +81,9 @@ public class CharacterArrayJavaType extends AbstractClassJavaType<Character[]> {
|
|||
if ( String.class.isAssignableFrom( type ) ) {
|
||||
return (X) new String( unwrapChars( value ) );
|
||||
}
|
||||
if ( NClob.class.isAssignableFrom( type ) ) {
|
||||
return (X) options.getLobCreator().createNClob( new String( unwrapChars( value ) ) );
|
||||
}
|
||||
if ( Clob.class.isAssignableFrom( type ) ) {
|
||||
return (X) options.getLobCreator().createClob( new String( unwrapChars( value ) ) );
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Clob} handling.
|
||||
|
@ -33,6 +32,7 @@ import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
|||
* But we treat them as immutable because we simply have no way to dirty check nor deep copy them.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Loïc Lefèvre
|
||||
*/
|
||||
public class ClobJavaType extends AbstractClassJavaType<Clob> {
|
||||
public static final ClobJavaType INSTANCE = new ClobJavaType();
|
||||
|
@ -107,7 +107,7 @@ public class ClobJavaType extends AbstractClassJavaType<Clob> {
|
|||
else if (Clob.class.isAssignableFrom( type )) {
|
||||
final Clob clob = value instanceof WrappedClob
|
||||
? ( (WrappedClob) value ).getWrappedClob()
|
||||
: value;
|
||||
: getOrCreateClob(value, options);
|
||||
return (X) clob;
|
||||
}
|
||||
else if ( String.class.isAssignableFrom( type ) ) {
|
||||
|
@ -128,6 +128,21 @@ public class ClobJavaType extends AbstractClassJavaType<Clob> {
|
|||
throw unknownUnwrap( type );
|
||||
}
|
||||
|
||||
private Clob getOrCreateClob(Clob value, WrapperOptions options) throws SQLException {
|
||||
if(options.getDialect().useConnectionToCreateLob()) {
|
||||
if(value.length() == 0) {
|
||||
// empty Clob
|
||||
return options.getLobCreator().createClob("");
|
||||
}
|
||||
else {
|
||||
return options.getLobCreator().createClob(value.getSubString(1, (int) value.length()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public <X> Clob wrap(X value, WrapperOptions options) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.hibernate.type.descriptor.WrapperOptions;
|
|||
* treat them as immutable because we cannot properly check them for changes nor deep copy them.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Loïc Lefèvre
|
||||
*/
|
||||
public class NClobJavaType extends AbstractClassJavaType<NClob> {
|
||||
public static final NClobJavaType INSTANCE = new NClobJavaType();
|
||||
|
@ -105,7 +106,7 @@ public class NClobJavaType extends AbstractClassJavaType<NClob> {
|
|||
else if (NClob.class.isAssignableFrom( type )) {
|
||||
final NClob nclob = value instanceof WrappedNClob
|
||||
? ( (WrappedNClob) value ).getWrappedNClob()
|
||||
: value;
|
||||
: getOrCreateNClob(value, options);
|
||||
return (X) nclob;
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +117,22 @@ public class NClobJavaType extends AbstractClassJavaType<NClob> {
|
|||
throw unknownUnwrap( type );
|
||||
}
|
||||
|
||||
private NClob getOrCreateNClob(NClob value, WrapperOptions options) throws SQLException {
|
||||
if(options.getDialect().useConnectionToCreateLob()) {
|
||||
if(value.length() == 0) {
|
||||
// empty NClob
|
||||
return options.getLobCreator().createNClob("");
|
||||
}
|
||||
else {
|
||||
return options.getLobCreator().createNClob(value.getSubString(1, (int) value.length()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public <X> NClob wrap(X value, WrapperOptions options) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.type.descriptor.java;
|
|||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.sql.Clob;
|
||||
import java.sql.NClob;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.hibernate.engine.jdbc.CharacterStream;
|
||||
|
@ -62,6 +63,9 @@ public class PrimitiveCharacterArrayJavaType extends AbstractClassJavaType<char[
|
|||
if ( String.class.isAssignableFrom( type ) ) {
|
||||
return (X) new String( value );
|
||||
}
|
||||
if ( NClob.class.isAssignableFrom( type ) ) {
|
||||
return (X) options.getLobCreator().createNClob( new String( value ) );
|
||||
}
|
||||
if ( Clob.class.isAssignableFrom( type ) ) {
|
||||
return (X) options.getLobCreator().createClob( new String( value ) );
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.type.descriptor.java;
|
|||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.sql.Clob;
|
||||
import java.sql.NClob;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.engine.jdbc.CharacterStream;
|
||||
|
@ -76,6 +77,9 @@ public class StringJavaType extends AbstractClassJavaType<String> {
|
|||
if ( DataHelper.isNClob( type ) ) {
|
||||
return (X) options.getLobCreator().createNClob( value );
|
||||
}
|
||||
if ( NClob.class.isAssignableFrom( type ) ) {
|
||||
return (X) options.getLobCreator().createNClob( value );
|
||||
}
|
||||
if ( Clob.class.isAssignableFrom( type ) ) {
|
||||
return (X) options.getLobCreator().createClob( value );
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import java.sql.Blob;
|
|||
import java.sql.Clob;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.engine.jdbc.LobCreator;
|
||||
import org.hibernate.engine.jdbc.NonContextualLobCreator;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -78,6 +80,18 @@ public abstract class AbstractDescriptorTest<T> extends BaseUnitTestCase {
|
|||
public TimeZone getJdbcTimeZone() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private final Dialect dialect = new H2Dialect() {
|
||||
@Override
|
||||
public boolean useConnectionToCreateLob() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Dialect getDialect() {
|
||||
return dialect;
|
||||
}
|
||||
};
|
||||
|
||||
public AbstractDescriptorTest(JavaType<T> typeDescriptor) {
|
||||
|
|
|
@ -12,6 +12,8 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.engine.jdbc.LobCreator;
|
||||
import org.hibernate.engine.jdbc.NonContextualLobCreator;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -75,6 +77,18 @@ public class StringValueMappingTest {
|
|||
public TimeZone getJdbcTimeZone() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private final Dialect dialect = new H2Dialect() {
|
||||
@Override
|
||||
public boolean useConnectionToCreateLob() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Dialect getDialect() {
|
||||
return dialect;
|
||||
}
|
||||
};
|
||||
|
||||
public static final int COLUMN_POSITION = 0;
|
||||
|
|
Loading…
Reference in New Issue