HHH-18220 Detect if Application Continuity is enabled for Oracle dialect
This commit is contained in:
parent
58e814965e
commit
7c711751dd
|
@ -12,6 +12,7 @@ package org.hibernate.cfg;
|
|||
* its underlying JDBC {@link java.sql.Connection}.
|
||||
*
|
||||
* @author Marco Belladelli
|
||||
* @author Loïc Lefèvre
|
||||
*/
|
||||
public interface DialectSpecificSettings {
|
||||
/**
|
||||
|
@ -28,6 +29,15 @@ public interface DialectSpecificSettings {
|
|||
*/
|
||||
public static final String ORACLE_EXTENDED_STRING_SIZE = "hibernate.dialect.oracle.extended_string_size";
|
||||
|
||||
/**
|
||||
* Specifies whether this database is accessed using a database service protected by Application Continuity.
|
||||
*
|
||||
* @settingDefault {@code false}
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/jjdbc/application-continuity.html">Application Continuity for Java</a>
|
||||
*/
|
||||
public static final String ORACLE_APPLICATION_CONTINUITY = "hibernate.dialect.oracle.application_continuity";
|
||||
|
||||
/**
|
||||
* Specifies whether this database's {@code ansinull} setting is enabled.
|
||||
*
|
||||
|
|
|
@ -187,6 +187,9 @@ public class OracleDialect extends Dialect {
|
|||
// 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;
|
||||
|
@ -200,6 +203,7 @@ public class OracleDialect extends Dialect {
|
|||
super(version);
|
||||
autonomous = false;
|
||||
extended = false;
|
||||
applicationContinuity = false;
|
||||
driverMajorVersion = 19;
|
||||
driverMinorVersion = 0;
|
||||
}
|
||||
|
@ -212,6 +216,7 @@ public class OracleDialect extends Dialect {
|
|||
super( info );
|
||||
autonomous = serverConfiguration.isAutonomous();
|
||||
extended = serverConfiguration.isExtended();
|
||||
applicationContinuity = serverConfiguration.isApplicationContinuity();
|
||||
this.driverMinorVersion = serverConfiguration.getDriverMinorVersion();
|
||||
this.driverMajorVersion = serverConfiguration.getDriverMajorVersion();
|
||||
}
|
||||
|
@ -258,6 +263,10 @@ public class OracleDialect extends Dialect {
|
|||
return extended;
|
||||
}
|
||||
|
||||
public boolean isApplicationContinuity() {
|
||||
return applicationContinuity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DatabaseVersion getMinimumSupportedVersion() {
|
||||
return MINIMUM_VERSION;
|
||||
|
|
|
@ -6,15 +6,20 @@
|
|||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
|
||||
import oracle.jdbc.replay.ReplayStatistics;
|
||||
import oracle.jdbc.replay.ReplayableConnection;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
|
||||
import static oracle.jdbc.replay.ReplayableConnection.StatisticsReportType.FOR_CURRENT_CONNECTION;
|
||||
import static org.hibernate.cfg.DialectSpecificSettings.ORACLE_APPLICATION_CONTINUITY;
|
||||
import static org.hibernate.cfg.DialectSpecificSettings.ORACLE_AUTONOMOUS_DATABASE;
|
||||
import static org.hibernate.cfg.DialectSpecificSettings.ORACLE_EXTENDED_STRING_SIZE;
|
||||
|
||||
|
@ -22,10 +27,12 @@ import static org.hibernate.cfg.DialectSpecificSettings.ORACLE_EXTENDED_STRING_S
|
|||
* Utility class that extract some initial configuration from the database for {@link OracleDialect}.
|
||||
*
|
||||
* @author Marco Belladelli
|
||||
* @author Loïc Lefèvre
|
||||
*/
|
||||
public class OracleServerConfiguration {
|
||||
private final boolean autonomous;
|
||||
private final boolean extended;
|
||||
private final boolean applicationContinuity;
|
||||
private final int driverMajorVersion;
|
||||
private final int driverMinorVersion;
|
||||
|
||||
|
@ -37,6 +44,10 @@ public class OracleServerConfiguration {
|
|||
return extended;
|
||||
}
|
||||
|
||||
public boolean isApplicationContinuity() {
|
||||
return applicationContinuity;
|
||||
}
|
||||
|
||||
public int getDriverMajorVersion() {
|
||||
return driverMajorVersion;
|
||||
}
|
||||
|
@ -46,7 +57,7 @@ public class OracleServerConfiguration {
|
|||
}
|
||||
|
||||
public OracleServerConfiguration(boolean autonomous, boolean extended) {
|
||||
this( autonomous, extended, 19, 0 );
|
||||
this( autonomous, extended, false, 19, 0 );
|
||||
}
|
||||
|
||||
public OracleServerConfiguration(
|
||||
|
@ -54,8 +65,18 @@ public class OracleServerConfiguration {
|
|||
boolean extended,
|
||||
int driverMajorVersion,
|
||||
int driverMinorVersion) {
|
||||
this(autonomous, extended, false, driverMajorVersion, driverMinorVersion);
|
||||
}
|
||||
|
||||
public OracleServerConfiguration(
|
||||
boolean autonomous,
|
||||
boolean extended,
|
||||
boolean applicationContinuity,
|
||||
int driverMajorVersion,
|
||||
int driverMinorVersion) {
|
||||
this.autonomous = autonomous;
|
||||
this.extended = extended;
|
||||
this.applicationContinuity = applicationContinuity;
|
||||
this.driverMajorVersion = driverMajorVersion;
|
||||
this.driverMinorVersion = driverMinorVersion;
|
||||
}
|
||||
|
@ -63,6 +84,7 @@ public class OracleServerConfiguration {
|
|||
public static OracleServerConfiguration fromDialectResolutionInfo(DialectResolutionInfo info) {
|
||||
Boolean extended = null;
|
||||
Boolean autonomous = null;
|
||||
Boolean applicationContinuity = null;
|
||||
Integer majorVersion = null;
|
||||
Integer minorVersion = null;
|
||||
final DatabaseMetaData databaseMetaData = info.getDatabaseMetadata();
|
||||
|
@ -70,15 +92,51 @@ public class OracleServerConfiguration {
|
|||
majorVersion = databaseMetaData.getDriverMajorVersion();
|
||||
minorVersion = databaseMetaData.getDriverMinorVersion();
|
||||
|
||||
try (final Statement statement = databaseMetaData.getConnection().createStatement()) {
|
||||
final ResultSet rs = statement.executeQuery(
|
||||
"select cast('string' as varchar2(32000)), " +
|
||||
"sys_context('USERENV','CLOUD_SERVICE') from dual"
|
||||
);
|
||||
if ( rs.next() ) {
|
||||
// succeeded, so MAX_STRING_SIZE == EXTENDED
|
||||
extended = true;
|
||||
autonomous = isAutonomous( rs.getString( 2 ) );
|
||||
|
||||
try {
|
||||
final Connection c = databaseMetaData.getConnection();
|
||||
|
||||
// Use Oracle JDBC replay statistics information to determine if this
|
||||
// connection is protected by Application Continuity
|
||||
try {
|
||||
final ReplayableConnection re = (ReplayableConnection) c;
|
||||
ReplayStatistics stats = re.getReplayStatistics(FOR_CURRENT_CONNECTION);
|
||||
|
||||
final long totalRequests = stats.getTotalRequests();
|
||||
final long protectedCalls = stats.getTotalProtectedCalls();
|
||||
|
||||
try (final Statement s = c.createStatement()) {
|
||||
try (final ResultSet r = s.executeQuery("select 1 from dual")) {
|
||||
r.next();
|
||||
}
|
||||
}
|
||||
|
||||
stats = re.getReplayStatistics(FOR_CURRENT_CONNECTION);
|
||||
|
||||
// Application continuity is enabled on this database service if the number of
|
||||
// total requests and the number of protected calls for this connection have
|
||||
// both increased.
|
||||
applicationContinuity = stats.getTotalRequests() > totalRequests && stats.getTotalProtectedCalls() > protectedCalls;
|
||||
}
|
||||
catch(Exception e) {
|
||||
// A ClassCastException or a NullPointerException are expected here in the case
|
||||
// the Connection Factory is not the right one (not Replayable: ClassCastException)
|
||||
// or if the database service has not been configured (server side) to enable
|
||||
// application continuity (NullPointerException).
|
||||
applicationContinuity = false;
|
||||
}
|
||||
|
||||
// continue the checks...
|
||||
try (final Statement statement = c.createStatement()) {
|
||||
final ResultSet rs = statement.executeQuery(
|
||||
"select cast('string' as varchar2(32000)), " +
|
||||
"sys_context('USERENV','CLOUD_SERVICE') from dual"
|
||||
);
|
||||
if (rs.next()) {
|
||||
// succeeded, so MAX_STRING_SIZE == EXTENDED
|
||||
extended = true;
|
||||
autonomous = isAutonomous(rs.getString(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
|
@ -102,6 +160,13 @@ public class OracleServerConfiguration {
|
|||
false
|
||||
);
|
||||
}
|
||||
if ( applicationContinuity == null ) {
|
||||
applicationContinuity = ConfigurationHelper.getBoolean(
|
||||
ORACLE_APPLICATION_CONTINUITY,
|
||||
info.getConfigurationValues(),
|
||||
false
|
||||
);
|
||||
}
|
||||
if ( majorVersion == null ) {
|
||||
try {
|
||||
java.sql.Driver driver = java.sql.DriverManager.getDriver( "jdbc:oracle:thin:" );
|
||||
|
@ -114,7 +179,7 @@ public class OracleServerConfiguration {
|
|||
}
|
||||
|
||||
}
|
||||
return new OracleServerConfiguration( autonomous, extended, majorVersion, minorVersion );
|
||||
return new OracleServerConfiguration( autonomous, extended, applicationContinuity, majorVersion, minorVersion );
|
||||
}
|
||||
|
||||
private static boolean isAutonomous(String cloudServiceParam) {
|
||||
|
|
Loading…
Reference in New Issue