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 13a9cbae4eb8..8d27ff9b5232 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 @@ -1043,6 +1043,8 @@ public boolean supportsOuterJoinForUpdate() { @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 0dc198df18ef..3c533984ef13 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 @@ -870,6 +870,20 @@ public boolean supportsLobValueChangePropagation() { return false; } + @Override + 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; + } + @Override public boolean doesReadCommittedCauseWritersToBlockReaders() { return true; 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 57b9b7ce308a..ccb9206ea6a8 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 @@ -28,6 +28,7 @@ import org.hibernate.dialect.DmlTargetColumnQualifierSupport; import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.OracleServerConfiguration; import org.hibernate.dialect.OracleBooleanJdbcType; import org.hibernate.dialect.OracleJdbcHelper; import org.hibernate.dialect.OracleJsonJdbcType; @@ -188,16 +189,54 @@ public class OracleLegacyDialect extends Dialect { private final UniqueDelegate uniqueDelegate = new CreateTableUniqueDelegate(this); private final SequenceSupport oracleSequenceSupport = OracleSequenceSupport.getInstance(this); + // 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; + public OracleLegacyDialect() { this( DatabaseVersion.make( 8, 0 ) ); } public OracleLegacyDialect(DatabaseVersion version) { - super(version); + super( 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 ); + 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 @@ -1587,10 +1626,10 @@ 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 getDual() { return "dual"; 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 98c507ac35c2..27f526d1c1e9 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 @@ -861,6 +861,8 @@ public boolean supportsOuterJoinForUpdate() { @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 ec2ee505559e..09f712464641 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java @@ -1012,6 +1012,8 @@ public boolean supportsOuterJoinForUpdate() { @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 76a5ebce8973..0ac42af578b0 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -965,6 +965,20 @@ public boolean supportsLobValueChangePropagation() { return false; } + @Override + 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; + } + @Override public boolean doesReadCommittedCauseWritersToBlockReaders() { return true; 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 87529f6ec428..dbab33346ec8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java @@ -1710,10 +1710,10 @@ 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 getDual() { return "dual"; 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 33804afecdb5..e39bb3c9f4db 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -927,6 +927,8 @@ public boolean supportsOuterJoinForUpdate() { @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 686ff00674ee..c8b1988ff3cb 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 @@ -90,6 +90,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" ); @@ -109,7 +110,7 @@ public void testGenerateProxyStream() throws URISyntaxException { // H2, MySQL, Oracle, SQL Server work this way. // // - Blob blob = BlobProxy.generateProxy( stream, 1431 ); + Blob blob = BlobProxy.generateProxy( stream, length ); asset.setData( blob ); entityManager.persist( asset );