4
4
*/
5
5
package org .hibernate .dialect ;
6
6
7
- import java .lang .reflect .Field ;
8
7
import java .lang .reflect .Method ;
9
8
import java .sql .Connection ;
10
9
import java .sql .DatabaseMetaData ;
10
+ import java .sql .Driver ;
11
+ import java .sql .DriverManager ;
11
12
import java .sql .ResultSet ;
12
13
import java .sql .SQLException ;
13
14
import java .sql .Statement ;
14
- import java .util .List ;
15
+ import java .util .Map ;
15
16
16
17
import org .hibernate .engine .jdbc .dialect .spi .DialectResolutionInfo ;
17
- import org .hibernate .internal .util .config .ConfigurationHelper ;
18
18
19
19
import static org .hibernate .cfg .DialectSpecificSettings .ORACLE_APPLICATION_CONTINUITY ;
20
20
import static org .hibernate .cfg .DialectSpecificSettings .ORACLE_AUTONOMOUS_DATABASE ;
21
21
import static org .hibernate .cfg .DialectSpecificSettings .ORACLE_EXTENDED_STRING_SIZE ;
22
+ import static org .hibernate .internal .util .config .ConfigurationHelper .getBoolean ;
22
23
23
24
/**
24
25
* Utility class that extract some initial configuration from the database for {@link OracleDialect}.
@@ -62,7 +63,7 @@ public OracleServerConfiguration(
62
63
boolean extended ,
63
64
int driverMajorVersion ,
64
65
int driverMinorVersion ) {
65
- this (autonomous , extended , false , driverMajorVersion , driverMinorVersion );
66
+ this ( autonomous , extended , false , driverMajorVersion , driverMinorVersion );
66
67
}
67
68
68
69
public OracleServerConfiguration (
@@ -79,129 +80,124 @@ public OracleServerConfiguration(
79
80
}
80
81
81
82
public static OracleServerConfiguration fromDialectResolutionInfo (DialectResolutionInfo info ) {
82
- Boolean extended = null ;
83
- Boolean autonomous = null ;
84
- Boolean applicationContinuity = null ;
85
- Integer majorVersion = null ;
86
- Integer minorVersion = null ;
87
- final DatabaseMetaData databaseMetaData = info .getDatabaseMetadata ();
88
- if ( databaseMetaData != null ) {
89
- majorVersion = databaseMetaData .getDriverMajorVersion ();
90
- minorVersion = databaseMetaData .getDriverMinorVersion ();
91
83
92
-
93
- try {
94
- final Connection c = databaseMetaData .getConnection ();
95
-
96
- try (final Statement statement = c .createStatement ()) {
97
-
98
- // Use Oracle JDBC replay statistics information to determine if this
99
- // connection is protected by Application Continuity
100
- try {
101
- final Class statisticReportTypeEnum = Class .forName ("oracle.jdbc.replay.ReplayableConnection$StatisticsReportType" ,false , Thread .currentThread ().getContextClassLoader ());
102
- final Field forCurrentConnection = statisticReportTypeEnum .getField ("FOR_CURRENT_CONNECTION" );
103
-
104
- final Method getReplayStatistics = c .getClass ().getMethod ("getReplayStatistics" , statisticReportTypeEnum );
105
-
106
- Object stats = getReplayStatistics .invoke (c ,forCurrentConnection .get (null ));
107
-
108
- final Method getTotalRequests = stats .getClass ().getMethod ("getTotalRequests" );
109
- final Method getTotalProtectedCalls = stats .getClass ().getMethod ("getTotalProtectedCalls" );
110
-
111
- final Long totalRequestsBefore = (Long )getTotalRequests .invoke (stats );
112
- final Long protectedCallsBefore = (Long )getTotalProtectedCalls .invoke (stats );
113
-
114
- try (ResultSet r = statement .executeQuery ("select 1" )) {
115
- r .next ();
116
- }
117
-
118
- stats = getReplayStatistics .invoke (c ,forCurrentConnection .get (null ));
119
-
120
- final Long totalRequestsAfter = (Long )getTotalRequests .invoke (stats );
121
- final Long protectedCallsAfter = (Long )getTotalProtectedCalls .invoke (stats );
122
-
123
- // Application continuity is enabled on this database service if the number of
124
- // total requests and the number of protected calls for this connection have
125
- // both increased.
126
- applicationContinuity = totalRequestsAfter > totalRequestsBefore && protectedCallsAfter > protectedCallsBefore ;
127
- }
128
- catch (Exception e ) {
129
- // A ClassCastException or a NullPointerException are expected here in the case
130
- // the Connection Factory is not the right one (not Replayable: ClassCastException)
131
- // or if the database service has not been configured (server side) to enable
132
- // application continuity (NullPointerException).
133
- applicationContinuity = false ;
134
- }
135
-
136
- // continue the checks...
137
- final ResultSet rs = statement .executeQuery (
138
- "select cast('string' as varchar2(32000)), " +
139
- "sys_context('USERENV','CLOUD_SERVICE') from dual"
140
- );
141
- if (rs .next ()) {
142
- // succeeded, so MAX_STRING_SIZE == EXTENDED
143
- extended = true ;
144
- autonomous = isAutonomous (rs .getString (2 ));
145
- }
146
- }
147
- }
148
- catch (SQLException ex ) {
149
- // failed, so MAX_STRING_SIZE == STANDARD, still need to check autonomous
150
- extended = false ;
151
- autonomous = isAutonomous ( databaseMetaData );
152
- }
153
- }
154
84
// default to the dialect-specific configuration settings
155
- if ( extended == null ) {
156
- extended = ConfigurationHelper .getBoolean (
157
- ORACLE_EXTENDED_STRING_SIZE ,
158
- info .getConfigurationValues (),
159
- false
160
- );
161
- }
162
- if ( autonomous == null ) {
163
- autonomous = ConfigurationHelper .getBoolean (
164
- ORACLE_AUTONOMOUS_DATABASE ,
165
- info .getConfigurationValues (),
166
- false
167
- );
168
- }
169
- if ( applicationContinuity == null ) {
170
- applicationContinuity = ConfigurationHelper .getBoolean (
171
- ORACLE_APPLICATION_CONTINUITY ,
172
- info .getConfigurationValues (),
173
- false
174
- );
175
- }
176
- if ( majorVersion == null ) {
85
+ final Map <String , Object > configuration = info .getConfigurationValues ();
86
+ final boolean defaultExtended = getBoolean ( ORACLE_EXTENDED_STRING_SIZE , configuration , false );
87
+ final boolean defaultAutonomous = getBoolean ( ORACLE_AUTONOMOUS_DATABASE , configuration , false );
88
+ final boolean defaultContinuity = getBoolean ( ORACLE_APPLICATION_CONTINUITY , configuration , false );
89
+
90
+ boolean extended ;
91
+ boolean autonomous ;
92
+ boolean applicationContinuity ;
93
+ int majorVersion ;
94
+ int minorVersion ;
95
+ final DatabaseMetaData databaseMetaData = info .getDatabaseMetadata ();
96
+ if ( databaseMetaData == null ) {
97
+ extended = defaultExtended ;
98
+ autonomous = defaultAutonomous ;
99
+ applicationContinuity = defaultContinuity ;
177
100
try {
178
- java . sql . Driver driver = java . sql . DriverManager .getDriver ( "jdbc:oracle:thin:" );
101
+ final Driver driver = DriverManager .getDriver ( "jdbc:oracle:thin:" );
179
102
majorVersion = driver .getMajorVersion ();
180
103
minorVersion = driver .getMinorVersion ();
181
104
}
182
105
catch (SQLException ex ) {
183
106
majorVersion = 19 ;
184
107
minorVersion = 0 ;
185
108
}
186
-
187
109
}
110
+ else {
111
+ majorVersion = databaseMetaData .getDriverMajorVersion ();
112
+ minorVersion = databaseMetaData .getDriverMinorVersion ();
113
+ try {
114
+ final Connection connection = databaseMetaData .getConnection (); // we should not close this
115
+ try ( final Statement statement = connection .createStatement () ) {
116
+ applicationContinuity = determineApplicationContinuity ( connection , statement );
117
+ autonomous = isAutonomous ( statement );
118
+ extended = isExtended ( statement );
119
+ }
120
+ }
121
+ catch (SQLException sqle ) {
122
+ extended = defaultExtended ;
123
+ autonomous = defaultAutonomous ;
124
+ applicationContinuity = defaultContinuity ;
125
+ }
126
+ }
127
+
188
128
return new OracleServerConfiguration ( autonomous , extended , applicationContinuity , majorVersion , minorVersion );
189
129
}
190
130
191
- private static boolean isAutonomous (String cloudServiceParam ) {
192
- return cloudServiceParam != null && List .of ( "OLTP" , "DWCS" , "JDCS" ).contains ( cloudServiceParam );
131
+ private static boolean isExtended (Statement statement ) {
132
+ try ( final ResultSet resultSet =
133
+ statement .executeQuery ( "select cast('string' as varchar2(32000)) from dual" ) ) {
134
+ resultSet .next ();
135
+ // succeeded, so MAX_STRING_SIZE == EXTENDED
136
+ return true ;
137
+ }
138
+ catch (SQLException ex ) {
139
+ // failed, so MAX_STRING_SIZE == STANDARD, still need to check autonomous
140
+ return false ;
141
+ }
193
142
}
194
143
195
- private static boolean isAutonomous (DatabaseMetaData databaseMetaData ) {
196
- try (final Statement statement = databaseMetaData .getConnection ().createStatement ()) {
197
- return statement .executeQuery (
198
- "select 1 from dual where sys_context('USERENV','CLOUD_SERVICE') in ('OLTP','DWCS','JDCS')" )
199
- .next ();
144
+ private static Boolean determineApplicationContinuity (Connection connection , Statement statement ) {
145
+ // Use Oracle JDBC replay statistics information to determine if this
146
+ // connection is protected by Application Continuity
147
+ try {
148
+ final Class <?> statisticReportTypeEnum =
149
+ Class .forName ( "oracle.jdbc.replay.ReplayableConnection$StatisticsReportType" ,
150
+ false , Thread .currentThread ().getContextClassLoader () );
151
+ final Object forCurrentConnection =
152
+ statisticReportTypeEnum .getField ( "FOR_CURRENT_CONNECTION" ).get ( null );
153
+ final Method getReplayStatistics =
154
+ connection .getClass ().getMethod ( "getReplayStatistics" , statisticReportTypeEnum );
155
+ final Class <?> replayStatistics = getReplayStatistics .getReturnType ();
156
+ final Method getTotalRequests = replayStatistics .getMethod ("getTotalRequests" );
157
+ final Method getTotalProtectedCalls = replayStatistics .getMethod ("getTotalProtectedCalls" );
158
+
159
+ final Object before = getReplayStatistics .invoke ( connection , forCurrentConnection );
160
+ final Long totalRequestsBefore = (Long ) getTotalRequests .invoke ( before );
161
+ final Long protectedCallsBefore = (Long ) getTotalProtectedCalls .invoke ( before );
162
+
163
+ try ( final ResultSet resultSet = statement .executeQuery ("select 1" ) ) {
164
+ resultSet .next ();
165
+ }
166
+
167
+ final Object after = getReplayStatistics .invoke ( connection , forCurrentConnection );
168
+ final Long totalRequestsAfter = (Long ) getTotalRequests .invoke ( after );
169
+ final Long protectedCallsAfter = (Long ) getTotalProtectedCalls .invoke ( after );
170
+
171
+ // Application continuity is enabled on this database service if the number of
172
+ // total requests and the number of protected calls for this connection have
173
+ // both increased.
174
+ return totalRequestsAfter > totalRequestsBefore
175
+ && protectedCallsAfter > protectedCallsBefore ;
176
+ }
177
+ catch (Exception e ) {
178
+ // A ClassCastException or a NullPointerException are expected here in the case
179
+ // the Connection Factory is not the right one (not Replayable: ClassCastException)
180
+ // or if the database service has not been configured (server side) to enable
181
+ // application continuity (NullPointerException).
182
+ return false ;
183
+ }
184
+ }
185
+
186
+ private static boolean isAutonomous (Statement statement ) {
187
+ try ( final ResultSet resultSet =
188
+ statement .executeQuery ( "select sys_context('USERENV','CLOUD_SERVICE') from dual" ) ) {
189
+ return resultSet .next ()
190
+ && isAutonomous ( resultSet .getString (1 ) );
200
191
}
201
192
catch (SQLException ex ) {
202
- // Ignore
193
+ return false ;
203
194
}
204
- return false ;
205
195
}
206
196
197
+ private static boolean isAutonomous (String type ) {
198
+ return type != null && switch ( type ) {
199
+ case "OLTP" , "DWCS" , "JDCS" -> true ;
200
+ default -> false ;
201
+ };
202
+ }
207
203
}
0 commit comments