Skip to content

Commit a74fa89

Browse files
committed
possible mitigation for Oracle fetch size issue
1 parent 6a9bc9b commit a74fa89

File tree

5 files changed

+53
-8
lines changed

5 files changed

+53
-8
lines changed

hibernate-core/src/main/java/org/hibernate/engine/jdbc/JdbcLogging.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,24 +152,32 @@ public interface JdbcLogging extends BasicLogger {
152152
@Message(value = "Unable to roll back isolated connection on exception ", id = 100021)
153153
void unableToRollBackIsolatedConnection(@Cause Exception ignored);
154154

155+
@LogMessage(level = DEBUG)
156+
@Message(value = "Using default JDBC fetch size: %s", id = 100022)
157+
void usingFetchSize(int fetchSize);
158+
159+
@LogMessage(level = WARN)
160+
@Message(value = "Low default JDBC fetch size: %s (consider setting 'hibernate.jdbc.fetch_size')", id = 100023)
161+
void warnLowFetchSize(int fetchSize);
162+
155163
@LogMessage(level = TRACE)
156-
@Message(value = "JDBC fetch size: %s", id = 100022)
164+
@Message(value = "JDBC fetch size: %s", id = 100024)
157165
void fetchSize(int fetchSize);
158166

159167
@LogMessage(level = DEBUG)
160-
@Message(value = "Low JDBC fetch size: %s (consider setting 'hibernate.jdbc.fetch_size')", id = 100023)
168+
@Message(value = "Low JDBC fetch size: %s (consider setting 'hibernate.jdbc.fetch_size')", id = 100025)
161169
void lowFetchSize(int fetchSize);
162170

163171
@LogMessage(level = TRACE)
164-
@Message(value = "Setting JDBC fetch size: %s", id = 100024)
172+
@Message(value = "Setting JDBC fetch size: %s", id = 100026)
165173
void settingFetchSize(int fetchSize);
166174

167175
@LogMessage(level = TRACE)
168-
@Message(value = "Setting JDBC query timeout: %s", id = 100025)
176+
@Message(value = "Setting JDBC query timeout: %s", id = 100027)
169177
void settingQueryTimeout(int timeout);
170178

171179
@LogMessage(level = WARN)
172-
@Message(value = "Called joinTransaction() on a non-JTA EntityManager (ignoring)", id = 100026)
180+
@Message(value = "Called joinTransaction() on a non-JTA EntityManager (ignoring)", id = 100030)
173181
void callingJoinTransactionOnNonJtaEntityManager();
174182

175183
@LogMessage(level = TRACE)

hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.sql.DatabaseMetaData;
99
import java.sql.ResultSet;
1010
import java.sql.SQLException;
11+
import java.sql.Statement;
1112
import java.util.Collections;
1213
import java.util.List;
1314
import java.util.stream.Collectors;
@@ -49,7 +50,7 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
4950
private final String url;
5051
private final String driver;
5152
private final boolean jdbcMetadataAccessible;
52-
53+
private final int defaultFetchSize;
5354

5455
//Lazily initialized: loading all sequence information upfront has been
5556
//shown to be too slow in some cases. In this way we only load it
@@ -71,6 +72,7 @@ private ExtractedDatabaseMetaDataImpl(
7172
SQLStateType sqlStateType,
7273
int transactionIsolation,
7374
int defaultTransactionIsolation,
75+
int defaultFetchSize,
7476
String url,
7577
String driver,
7678
boolean jdbcMetadataIsAccessible) {
@@ -88,6 +90,7 @@ private ExtractedDatabaseMetaDataImpl(
8890
this.sqlStateType = sqlStateType;
8991
this.transactionIsolation = transactionIsolation;
9092
this.defaultTransactionIsolation = defaultTransactionIsolation;
93+
this.defaultFetchSize = defaultFetchSize;
9194
this.url = url;
9295
this.driver = driver;
9396
this.jdbcMetadataAccessible = jdbcMetadataIsAccessible;
@@ -168,6 +171,11 @@ public int getDefaultTransactionIsolation() {
168171
return defaultTransactionIsolation;
169172
}
170173

174+
@Override
175+
public int getDefaultFetchSize() {
176+
return defaultFetchSize;
177+
}
178+
171179
@Override
172180
public synchronized List<SequenceInformation> getSequenceInformationList() {
173181
if ( jdbcMetadataAccessible ) {
@@ -211,6 +219,7 @@ public static class Builder {
211219
private String driver;
212220
private int defaultTransactionIsolation;
213221
private int transactionIsolation;
222+
private int defaultFetchSize;
214223

215224
public Builder(JdbcEnvironment jdbcEnvironment, boolean jdbcMetadataIsAccessible, JdbcConnectionAccess connectionAccess) {
216225
this.jdbcEnvironment = jdbcEnvironment;
@@ -233,6 +242,12 @@ public Builder apply(DatabaseMetaData databaseMetaData) throws SQLException {
233242
driver = databaseMetaData.getDriverName();
234243
defaultTransactionIsolation = databaseMetaData.getDefaultTransactionIsolation();
235244
transactionIsolation = databaseMetaData.getConnection().getTransactionIsolation();
245+
try ( Statement statement = databaseMetaData.getConnection().createStatement() ) {
246+
defaultFetchSize = statement.getFetchSize();
247+
}
248+
catch (SQLException sqle) {
249+
defaultFetchSize = -1;
250+
}
236251
return this;
237252
}
238253

@@ -302,6 +317,7 @@ public ExtractedDatabaseMetaDataImpl build() {
302317
sqlStateType,
303318
transactionIsolation,
304319
defaultTransactionIsolation,
320+
defaultFetchSize,
305321
url,
306322
driver,
307323
jdbcMetadataIsAccessible

hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.hibernate.boot.model.naming.Identifier;
1111
import org.hibernate.boot.registry.selector.spi.StrategySelector;
1212
import org.hibernate.cfg.AvailableSettings;
13+
import org.hibernate.cfg.JdbcSettings;
1314
import org.hibernate.dialect.Dialect;
1415
import org.hibernate.engine.config.spi.ConfigurationService;
1516
import org.hibernate.engine.config.spi.StandardConverters;
@@ -38,6 +39,7 @@
3839
import static org.hibernate.cfg.MappingSettings.DEFAULT_CATALOG;
3940
import static org.hibernate.cfg.MappingSettings.DEFAULT_SCHEMA;
4041
import static org.hibernate.engine.config.spi.StandardConverters.STRING;
42+
import static org.hibernate.engine.jdbc.JdbcLogging.JDBC_MESSAGE_LOGGER;
4143
import static org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl.makeLobCreatorBuilder;
4244

4345
/**
@@ -105,6 +107,8 @@ public JdbcEnvironmentImpl(final ServiceRegistryImplementor serviceRegistry, fin
105107
new QualifiedObjectNameFormatterStandardImpl( nameQualifierSupport, dialect.getCatalogSeparator() );
106108

107109
lobCreatorBuilder = makeLobCreatorBuilder( dialect );
110+
111+
logJdbcFetchSize( extractedMetaDataSupport.getDefaultFetchSize(), cfgService );
108112
}
109113

110114
private static ConfigurationService configurationService(ServiceRegistryImplementor serviceRegistry) {
@@ -317,6 +321,8 @@ public JdbcEnvironmentImpl(
317321
new QualifiedObjectNameFormatterStandardImpl( nameQualifierSupport, databaseMetaData );
318322

319323
lobCreatorBuilder = makeLobCreatorBuilder( dialect, cfgService.getSettings(), databaseMetaData.getConnection() );
324+
325+
logJdbcFetchSize( extractedMetaDataSupport.getDefaultFetchSize(), cfgService );
320326
}
321327

322328
private static IdentifierHelper identifierHelper(
@@ -420,4 +426,14 @@ public LobCreatorBuilder getLobCreatorBuilder() {
420426
return lobCreatorBuilder;
421427
}
422428

429+
private static void logJdbcFetchSize(int defaultFetchSize, ConfigurationService cfgService) {
430+
if ( !cfgService.getSettings().containsKey( JdbcSettings.STATEMENT_FETCH_SIZE ) ) {
431+
if ( defaultFetchSize > 0 && defaultFetchSize < 100 ) {
432+
JDBC_MESSAGE_LOGGER.warnLowFetchSize( defaultFetchSize );
433+
}
434+
else {
435+
JDBC_MESSAGE_LOGGER.usingFetchSize( defaultFetchSize );
436+
}
437+
}
438+
}
423439
}

hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ public interface ExtractedDatabaseMetaData {
150150
*/
151151
int getDefaultTransactionIsolation();
152152

153+
/**
154+
* Retrieve the default JDBC {@link java.sql.Statement#getFetchSize fetch size}.
155+
*/
156+
int getDefaultFetchSize();
157+
153158
/**
154159
* Retrieve the list of {@code SequenceInformation} objects which describe the underlying database sequences.
155160
*

hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/StatementPreparerImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ private void setStatementFetchSize(PreparedStatement statement) throws SQLExcept
234234
else {
235235
if ( JDBC_MESSAGE_LOGGER.isDebugEnabled() ) {
236236
final int defaultFetchSize = statement.getFetchSize();
237-
if ( defaultFetchSize < 100 ) {
238-
JDBC_MESSAGE_LOGGER.lowFetchSize( statement.getFetchSize() );
237+
if ( defaultFetchSize > 0 && defaultFetchSize < 100 ) {
238+
JDBC_MESSAGE_LOGGER.lowFetchSize( defaultFetchSize );
239239
}
240240
}
241241
else if ( JDBC_MESSAGE_LOGGER.isTraceEnabled() ) {

0 commit comments

Comments
 (0)