7
7
import java .sql .PreparedStatement ;
8
8
import java .sql .ResultSet ;
9
9
import java .sql .SQLException ;
10
- import java .util .Collections ;
11
10
12
11
import org .hibernate .LockMode ;
13
12
import org .hibernate .LockOptions ;
14
13
import org .hibernate .dialect .Dialect ;
15
14
import org .hibernate .dialect .pagination .LimitHandler ;
16
15
import org .hibernate .dialect .pagination .NoopLimitHandler ;
16
+ import org .hibernate .engine .jdbc .spi .JdbcServices ;
17
17
import org .hibernate .engine .jdbc .spi .SqlStatementLogger ;
18
18
import org .hibernate .engine .spi .SessionEventListenerManager ;
19
19
import org .hibernate .engine .spi .SessionFactoryImplementor ;
33
33
import org .hibernate .sql .exec .spi .JdbcParameterBindings ;
34
34
import org .hibernate .sql .exec .spi .JdbcSelectExecutor ;
35
35
36
+ import static java .util .Collections .emptyMap ;
37
+
36
38
/**
37
39
* @author Steve Ebersole
38
40
*/
@@ -62,11 +64,13 @@ public DeferredResultSetAccess(
62
64
JdbcSelectExecutor .StatementCreator statementCreator ,
63
65
int resultCountEstimate ) {
64
66
super ( executionContext .getSession () );
67
+ final JdbcServices jdbcServices = executionContext .getSession ().getJdbcServices ();
68
+
65
69
this .jdbcParameterBindings = jdbcParameterBindings ;
66
70
this .executionContext = executionContext ;
67
71
this .jdbcSelect = jdbcSelect ;
68
72
this .statementCreator = statementCreator ;
69
- this .sqlStatementLogger = executionContext . getSession (). getJdbcServices () .getSqlStatementLogger ();
73
+ this .sqlStatementLogger = jdbcServices .getSqlStatementLogger ();
70
74
this .resultCountEstimate = resultCountEstimate ;
71
75
72
76
final QueryOptions queryOptions = executionContext .getQueryOptions ();
@@ -79,54 +83,61 @@ public DeferredResultSetAccess(
79
83
else {
80
84
// Note that limit and lock aren't set for SQM as that is applied during SQL rendering
81
85
// But for native queries, we have to adapt the SQL string
82
- final Dialect dialect = executionContext .getSession ().getJdbcServices ().getDialect ();
83
- String sql ;
86
+ final Dialect dialect = jdbcServices .getDialect ();
87
+
88
+ final String sql = jdbcSelect .getSqlString ();
89
+
84
90
limit = queryOptions .getLimit ();
85
- if ( limit == null || limit .isEmpty () || jdbcSelect .usesLimitParameters () ) {
86
- sql = jdbcSelect .getSqlString ();
87
- limitHandler = NoopLimitHandler .NO_LIMIT ;
88
- }
89
- else {
90
- limitHandler = dialect .getLimitHandler ();
91
- sql = limitHandler .processSql (
92
- jdbcSelect .getSqlString (),
93
- limit ,
94
- queryOptions
95
- );
96
- }
91
+ final boolean hasLimit = isHasLimit ( jdbcSelect );
92
+ limitHandler = hasLimit ? NoopLimitHandler .NO_LIMIT : dialect .getLimitHandler ();
93
+ final String sqlWithLimit = hasLimit ? sql : limitHandler .processSql ( sql , limit , queryOptions );
97
94
98
95
final LockOptions lockOptions = queryOptions .getLockOptions ();
99
96
final JdbcLockStrategy jdbcLockStrategy = jdbcSelect .getLockStrategy ();
100
- if ( jdbcLockStrategy != JdbcLockStrategy . NONE
101
- && lockOptions != null && ! lockOptions . isEmpty ( ) ) {
102
- usesFollowOnLocking = useFollowOnLocking ( jdbcLockStrategy , sql , queryOptions , lockOptions , dialect );
97
+ final String sqlWithLocking ;
98
+ if ( hasLocking ( jdbcLockStrategy , lockOptions ) ) {
99
+ usesFollowOnLocking = useFollowOnLocking ( jdbcLockStrategy , sqlWithLimit , queryOptions , lockOptions , dialect );
103
100
if ( usesFollowOnLocking ) {
104
- final LockMode lockMode = determineFollowOnLockMode ( lockOptions );
105
- if ( lockMode != LockMode .UPGRADE_SKIPLOCKED ) {
106
- // Dialect prefers to perform locking in a separate step
107
- if ( lockOptions .getLockMode () != LockMode .NONE ) {
108
- LOG .usingFollowOnLocking ();
109
- }
110
-
111
- final LockOptions lockOptionsToUse = new LockOptions ( lockMode );
112
- lockOptionsToUse .setTimeOut ( lockOptions .getTimeOut () );
113
- lockOptionsToUse .setLockScope ( lockOptions .getLockScope () );
114
-
115
- registerAfterLoadAction ( executionContext , lockOptionsToUse );
116
- }
101
+ handleFollowOnLocking ( executionContext , lockOptions );
102
+ sqlWithLocking = sqlWithLimit ;
117
103
}
118
104
else {
119
- sql = dialect .applyLocksToSql ( sql , lockOptions , Collections . emptyMap () );
105
+ sqlWithLocking = dialect .applyLocksToSql ( sqlWithLimit , lockOptions , emptyMap () );
120
106
}
121
107
}
122
108
else {
123
109
usesFollowOnLocking = false ;
110
+ sqlWithLocking = sqlWithLimit ;
124
111
}
125
- finalSql = dialect .addSqlHintOrComment (
126
- sql ,
127
- queryOptions ,
128
- executionContext .getSession ().getFactory ().getSessionFactoryOptions ().isCommentsEnabled ()
129
- );
112
+
113
+ final boolean commentsEnabled =
114
+ executionContext .getSession ().getFactory ()
115
+ .getSessionFactoryOptions ().isCommentsEnabled ();
116
+ finalSql = dialect .addSqlHintOrComment ( sqlWithLocking , queryOptions , commentsEnabled );
117
+ }
118
+ }
119
+
120
+ private boolean isHasLimit (JdbcOperationQuerySelect jdbcSelect ) {
121
+ return limit == null || limit .isEmpty () || jdbcSelect .usesLimitParameters ();
122
+ }
123
+
124
+ private static boolean hasLocking (JdbcLockStrategy jdbcLockStrategy , LockOptions lockOptions ) {
125
+ return jdbcLockStrategy != JdbcLockStrategy .NONE && lockOptions != null && !lockOptions .isEmpty ();
126
+ }
127
+
128
+ private void handleFollowOnLocking (ExecutionContext executionContext , LockOptions lockOptions ) {
129
+ final LockMode lockMode = determineFollowOnLockMode ( lockOptions );
130
+ if ( lockMode != LockMode .UPGRADE_SKIPLOCKED ) {
131
+ // Dialect prefers to perform locking in a separate step
132
+ if ( lockOptions .getLockMode () != LockMode .NONE ) {
133
+ LOG .usingFollowOnLocking ();
134
+ }
135
+
136
+ final LockOptions lockOptionsToUse = new LockOptions ( lockMode );
137
+ lockOptionsToUse .setTimeOut ( lockOptions .getTimeOut () );
138
+ lockOptionsToUse .setLockScope ( lockOptions .getLockScope () );
139
+
140
+ registerAfterLoadAction ( executionContext , lockOptionsToUse );
130
141
}
131
142
}
132
143
@@ -184,20 +195,10 @@ public boolean usesFollowOnLocking() {
184
195
}
185
196
186
197
protected void bindParameters (PreparedStatement preparedStatement ) throws SQLException {
187
- final QueryOptions queryOptions = executionContext .getQueryOptions ();
188
-
189
- // set options
190
- if ( queryOptions != null ) {
191
- if ( queryOptions .getFetchSize () != null ) {
192
- preparedStatement .setFetchSize ( queryOptions .getFetchSize () );
193
- }
194
- if ( queryOptions .getTimeout () != null ) {
195
- preparedStatement .setQueryTimeout ( queryOptions .getTimeout () );
196
- }
197
- }
198
+ setQueryOptions ( preparedStatement );
198
199
199
200
// bind parameters
200
- // todo : validate that all query parameters were bound?
201
+ // todo : validate that all query parameters were bound?
201
202
int paramBindingPosition = 1 ;
202
203
paramBindingPosition += limitHandler .bindLimitParametersAtStartOfQuery ( limit , preparedStatement , paramBindingPosition );
203
204
for ( JdbcParameterBinder parameterBinder : jdbcSelect .getParameterBinders () ) {
@@ -208,7 +209,6 @@ protected void bindParameters(PreparedStatement preparedStatement) throws SQLExc
208
209
executionContext
209
210
);
210
211
}
211
-
212
212
paramBindingPosition += limitHandler .bindLimitParametersAtEndOfQuery ( limit , preparedStatement , paramBindingPosition );
213
213
214
214
if ( !jdbcSelect .usesLimitParameters () && limit != null && limit .getMaxRows () != null ) {
@@ -222,6 +222,19 @@ protected void bindParameters(PreparedStatement preparedStatement) throws SQLExc
222
222
}
223
223
}
224
224
225
+ private void setQueryOptions (PreparedStatement preparedStatement ) throws SQLException {
226
+ final QueryOptions queryOptions = executionContext .getQueryOptions ();
227
+ // set options
228
+ if ( queryOptions != null ) {
229
+ if ( queryOptions .getFetchSize () != null ) {
230
+ preparedStatement .setFetchSize ( queryOptions .getFetchSize () );
231
+ }
232
+ if ( queryOptions .getTimeout () != null ) {
233
+ preparedStatement .setQueryTimeout ( queryOptions .getTimeout () );
234
+ }
235
+ }
236
+ }
237
+
225
238
private void executeQuery () {
226
239
final LogicalConnectionImplementor logicalConnection =
227
240
getPersistenceContext ().getJdbcCoordinator ().getLogicalConnection ();
@@ -234,9 +247,7 @@ private void executeQuery() {
234
247
235
248
bindParameters ( preparedStatement );
236
249
237
- final SessionEventListenerManager eventListenerManager = session
238
- .getEventListenerManager ();
239
-
250
+ final SessionEventListenerManager eventListenerManager = session .getEventListenerManager ();
240
251
long executeStartNanos = 0 ;
241
252
if ( sqlStatementLogger .getLogSlowQuery () > 0 ) {
242
253
executeStartNanos = System .nanoTime ();
@@ -257,17 +268,15 @@ private void executeQuery() {
257
268
skipRows ( resultSet );
258
269
logicalConnection .getResourceRegistry ().register ( resultSet , preparedStatement );
259
270
}
260
- catch (SQLException e ) {
271
+ catch (SQLException exception ) {
261
272
try {
262
273
release ();
263
274
}
264
- catch (RuntimeException e2 ) {
265
- e .addSuppressed ( e2 );
275
+ catch (RuntimeException suppressed ) {
276
+ exception .addSuppressed ( suppressed );
266
277
}
267
- throw session .getJdbcServices ().getSqlExceptionHelper ().convert (
268
- e ,
269
- "JDBC exception executing SQL [" + finalSql + "]"
270
- );
278
+ throw session .getJdbcServices ().getSqlExceptionHelper ()
279
+ .convert ( exception , "JDBC exception executing SQL [" + finalSql + "]" );
271
280
}
272
281
}
273
282
@@ -277,13 +286,7 @@ private JdbcSessionContext context() {
277
286
278
287
protected void skipRows (ResultSet resultSet ) throws SQLException {
279
288
// For dialects that don't support an offset clause
280
- final int rowsToSkip ;
281
- if ( !jdbcSelect .usesLimitParameters () && limit != null && limit .getFirstRow () != null && !limitHandler .supportsLimitOffset () ) {
282
- rowsToSkip = limit .getFirstRow ();
283
- }
284
- else {
285
- rowsToSkip = jdbcSelect .getRowsToSkip ();
286
- }
289
+ final int rowsToSkip = getRowsToSkip ();
287
290
if ( rowsToSkip != 0 ) {
288
291
try {
289
292
resultSet .absolute ( rowsToSkip );
@@ -303,13 +306,20 @@ protected void skipRows(ResultSet resultSet) throws SQLException {
303
306
}
304
307
}
305
308
309
+ private int getRowsToSkip () {
310
+ return !jdbcSelect .usesLimitParameters ()
311
+ && limit != null && limit .getFirstRow () != null
312
+ && !limitHandler .supportsLimitOffset ()
313
+ ? limit .getFirstRow ()
314
+ : jdbcSelect .getRowsToSkip ();
315
+ }
316
+
306
317
protected ResultSet wrapResultSet (ResultSet resultSet ) throws SQLException {
307
318
return resultSet ;
308
319
}
309
320
310
321
protected LockMode determineFollowOnLockMode (LockOptions lockOptions ) {
311
322
final LockMode lockModeToUse = lockOptions .findGreatestLockMode ();
312
-
313
323
if ( lockOptions .hasAliasSpecificLockModes () ) {
314
324
if ( lockOptions .getLockMode () == LockMode .NONE && lockModeToUse == LockMode .NONE ) {
315
325
return lockModeToUse ;
@@ -323,8 +333,8 @@ protected LockMode determineFollowOnLockMode(LockOptions lockOptions) {
323
333
324
334
@ Override
325
335
public void release () {
326
- final LogicalConnectionImplementor logicalConnection = getPersistenceContext (). getJdbcCoordinator ()
327
- .getLogicalConnection ();
336
+ final LogicalConnectionImplementor logicalConnection =
337
+ getPersistenceContext (). getJdbcCoordinator () .getLogicalConnection ();
328
338
if ( resultSet != null ) {
329
339
logicalConnection .getResourceRegistry ().release ( resultSet , preparedStatement );
330
340
resultSet = null ;
@@ -343,12 +353,14 @@ public int getResultCountEstimate() {
343
353
if ( limit != null && limit .getMaxRows () != null ) {
344
354
return limit .getMaxRows ();
345
355
}
346
- if ( jdbcSelect .getLimitParameter () != null ) {
356
+ else if ( jdbcSelect .getLimitParameter () != null ) {
347
357
return (int ) jdbcParameterBindings .getBinding ( jdbcSelect .getLimitParameter () ).getBindValue ();
348
358
}
349
- if ( resultCountEstimate > 0 ) {
359
+ else if ( resultCountEstimate > 0 ) {
350
360
return resultCountEstimate ;
351
361
}
352
- return super .getResultCountEstimate ();
362
+ else {
363
+ return super .getResultCountEstimate ();
364
+ }
353
365
}
354
366
}
0 commit comments