diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java index 25ff2c9fcea8..c31ceca11f18 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java @@ -1094,6 +1094,8 @@ public LockingSupport getLockingSupport() { @Override public boolean useInputStreamToInsertBlob() { + // PG-JDBC treats setBinaryStream()/setCharacterStream() calls like bytea/varchar, which are not LOBs, + // so disable stream bindings for this dialect completely return false; } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java index 7b165775a200..001ab14a7501 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java @@ -1095,7 +1095,16 @@ public boolean supportsLobValueChangePropagation() { } @Override - public boolean useInputStreamToInsertBlob() { + public boolean useConnectionToCreateLob() { + return false; + } + + @Override + public boolean supportsNationalizedMethods() { + // See HHH-12753, HHH-18314, HHH-19201 + // Old DB2 JDBC drivers do not support setNClob, setNCharcterStream or setNString. + // In more recent driver versions, some methods just delegate to the non-N variant, but others still fail. + // Ultimately, let's just avoid the N variant methods on DB2 altogether return false; } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java index 91c59b8af375..0d850ca13620 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java @@ -29,6 +29,7 @@ import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.DmlTargetColumnQualifierSupport; +import org.hibernate.dialect.OracleServerConfiguration; import org.hibernate.dialect.temptable.OracleLocalTemporaryTableStrategy; import org.hibernate.dialect.temptable.StandardGlobalTemporaryTableStrategy; import org.hibernate.dialect.temptable.TemporaryTableStrategy; @@ -206,6 +207,18 @@ protected void applyAggregateColumnCheck(StringBuilder buf, AggregateColumn aggr } }; + // Is it an Autonomous Database Cloud Service? + protected final boolean autonomous; + + // Is MAX_STRING_SIZE set to EXTENDED? + protected final boolean extended; + + // Is the database accessed using a database service protected by Application Continuity. + protected final boolean applicationContinuity; + + protected final int driverMajorVersion; + protected final int driverMinorVersion; + private final LockingSupport lockingSupport; public OracleLegacyDialect() { @@ -213,13 +226,39 @@ public OracleLegacyDialect() { } public OracleLegacyDialect(DatabaseVersion version) { - super(version); + super( version ); lockingSupport = new OracleLockingSupport( version ); + autonomous = false; + extended = false; + applicationContinuity = false; + driverMajorVersion = 19; + driverMinorVersion = 0; } public OracleLegacyDialect(DialectResolutionInfo info) { - super(info); + this( info, OracleServerConfiguration.fromDialectResolutionInfo( info ) ); + } + + public OracleLegacyDialect(DialectResolutionInfo info, OracleServerConfiguration serverConfiguration) { + super( info ); lockingSupport = new OracleLockingSupport( getVersion() ); + autonomous = serverConfiguration.isAutonomous(); + extended = serverConfiguration.isExtended(); + applicationContinuity = serverConfiguration.isApplicationContinuity(); + this.driverMinorVersion = serverConfiguration.getDriverMinorVersion(); + this.driverMajorVersion = serverConfiguration.getDriverMajorVersion(); + } + + public boolean isAutonomous() { + return autonomous; + } + + public boolean isExtended() { + return extended; + } + + public boolean isApplicationContinuity() { + return applicationContinuity; } @Override @@ -1661,11 +1700,11 @@ public boolean supportsFromClauseInUpdate() { @Override public boolean useInputStreamToInsertBlob() { - // see HHH-18206 - return false; + // If application continuity is enabled, don't use stream bindings, since a replay could otherwise fail + // if the underlying stream doesn't support mark and reset + return !isApplicationContinuity(); } - @Override public String appendCheckConstraintOptions(CheckConstraint checkConstraint, String sqlCheckConstraint) { if ( StringHelper.isNotEmpty( checkConstraint.getOptions() ) ) { diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java index 91debe50d7dd..8e99619e5be3 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java @@ -944,6 +944,8 @@ public GenerationType getNativeValueGenerationStrategy() { @Override public boolean useInputStreamToInsertBlob() { + // PG-JDBC treats setBinaryStream()/setCharacterStream() calls like bytea/varchar, which are not LOBs, + // so disable stream bindings for this dialect completely return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java index 5c11e834894d..1b2e27659988 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java @@ -992,6 +992,8 @@ public String getForUpdateSkipLockedString(String aliases) { @Override public boolean useInputStreamToInsertBlob() { + // PG-JDBC treats setBinaryStream()/setCharacterStream() calls like bytea/varchar, which are not LOBs, + // so disable stream bindings for this dialect completely return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java index b879a94a7f3c..8802e7ac1dab 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -895,7 +895,16 @@ public boolean supportsLobValueChangePropagation() { } @Override - public boolean useInputStreamToInsertBlob() { + public boolean useConnectionToCreateLob() { + return false; + } + + @Override + public boolean supportsNationalizedMethods() { + // See HHH-12753, HHH-18314, HHH-19201 + // Old DB2 JDBC drivers do not support setNClob, setNCharcterStream or setNString. + // In more recent driver versions, some methods just delegate to the non-N variant, but others still fail. + // Ultimately, let's just avoid the N variant methods on DB2 altogether return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java index e9e75adcc0ef..9d2e0f5ced88 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java @@ -1810,11 +1810,11 @@ public String[] getDropEnumTypeCommand(String name) { @Override public boolean useInputStreamToInsertBlob() { - // see HHH-18206 - return false; + // If application continuity is enabled, don't use stream bindings, since a replay could otherwise fail + // if the underlying stream doesn't support mark and reset + return !isApplicationContinuity(); } - @Override public String appendCheckConstraintOptions(CheckConstraint checkConstraint, String sqlCheckConstraint) { return isNotEmpty( checkConstraint.getOptions() ) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java index 54fd00b75940..87812301207b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -902,6 +902,8 @@ public GenerationType getNativeValueGenerationStrategy() { @Override public boolean useInputStreamToInsertBlob() { + // PG-JDBC treats setBinaryStream()/setCharacterStream() calls like bytea/varchar, which are not LOBs, + // so disable stream bindings for this dialect completely return false; } diff --git a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/blob/BasicBlobTest.java b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/blob/BasicBlobTest.java index 74d7ead88bd2..02baf048950e 100644 --- a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/blob/BasicBlobTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/blob/BasicBlobTest.java @@ -89,6 +89,7 @@ public void testGenerateProxyStream() throws URISyntaxException { .getResource( "org/hibernate/orm/test/envers/integration/blob/blob.txt" ).toURI() ); try (final InputStream stream = new BufferedInputStream( Files.newInputStream( path ) )) { + final long length = Files.size( path ); doInJPA( this::entityManagerFactory, entityManager -> { final Asset asset = new Asset(); asset.setFileName( "blob.txt" ); @@ -108,7 +109,7 @@ public void testGenerateProxyStream() throws URISyntaxException { // H2, MySQL, Oracle, SQL Server work this way. // // - Blob blob = BlobProxy.generateProxy( stream, 9192L ); + Blob blob = BlobProxy.generateProxy( stream, length ); asset.setData( blob ); entityManager.persist( asset );