HHH-1168 - Problem combining locking and paging on Oracle
(cherry picked from commit 6e71a0907e
)
This commit is contained in:
parent
a3a024ec34
commit
08d5d994dc
|
@ -2321,7 +2321,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsLockingAndPaging() {
|
||||
return true;
|
||||
public boolean useFollowOnLocking() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -578,7 +578,7 @@ public class Oracle8iDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsLockingAndPaging() {
|
||||
return false;
|
||||
public boolean useFollowOnLocking() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1586,9 +1586,9 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
|
||||
@LogMessage(level = WARN)
|
||||
@Message(
|
||||
value = "Encountered request which combined locking and paging, however dialect reports that database does " +
|
||||
"not support that combination. Results will be locked after initial query executes",
|
||||
value = "Encountered request for locking however dialect reports that database prefers locking be done in a " +
|
||||
"separate select; results will be locked after initial query executes",
|
||||
id = 444
|
||||
)
|
||||
void delayedLockingDueToPaging();
|
||||
void usingFollowOnLocking();
|
||||
}
|
||||
|
|
|
@ -249,30 +249,23 @@ public abstract class Loader {
|
|||
public void afterLoad(SessionImplementor session, Object entity, Loadable persister);
|
||||
}
|
||||
|
||||
protected boolean shouldDelayLockingDueToPaging(
|
||||
String sql,
|
||||
protected boolean shouldUseFollowOnLocking(
|
||||
QueryParameters parameters,
|
||||
Dialect dialect,
|
||||
List<AfterLoadAction> afterLoadActions) {
|
||||
final LockOptions lockOptions = parameters.getLockOptions();
|
||||
final RowSelection rowSelection = parameters.getRowSelection();
|
||||
final LimitHandler limitHandler = dialect.buildLimitHandler( sql, rowSelection );
|
||||
if ( LimitHelper.useLimit( limitHandler, rowSelection ) ) {
|
||||
// user has requested a combination of paging and locking. See if the dialect supports that
|
||||
// (ahem, Oracle...)
|
||||
if ( ! dialect.supportsLockingAndPaging() ) {
|
||||
LOG.delayedLockingDueToPaging();
|
||||
afterLoadActions.add(
|
||||
new AfterLoadAction() {
|
||||
private final LockOptions originalLockOptions = lockOptions.makeCopy();
|
||||
@Override
|
||||
public void afterLoad(SessionImplementor session, Object entity, Loadable persister) {
|
||||
( (Session) session ).buildLockRequest( originalLockOptions ).lock( persister.getEntityName(), entity );
|
||||
}
|
||||
if ( dialect.useFollowOnLocking() ) {
|
||||
LOG.usingFollowOnLocking();
|
||||
final LockOptions lockOptions = parameters.getLockOptions();
|
||||
afterLoadActions.add(
|
||||
new AfterLoadAction() {
|
||||
private final LockOptions originalLockOptions = lockOptions.makeCopy();
|
||||
@Override
|
||||
public void afterLoad(SessionImplementor session, Object entity, Loadable persister) {
|
||||
( (Session) session ).buildLockRequest( originalLockOptions ).lock( persister.getEntityName(), entity );
|
||||
}
|
||||
);
|
||||
parameters.setLockOptions( new LockOptions() );
|
||||
}
|
||||
}
|
||||
);
|
||||
parameters.setLockOptions( new LockOptions() );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -38,11 +38,8 @@ import org.hibernate.ScrollMode;
|
|||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
import org.hibernate.dialect.pagination.LimitHelper;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.CriteriaImpl;
|
||||
|
@ -207,43 +204,27 @@ public class CriteriaLoader extends OuterJoinLoader {
|
|||
return sql;
|
||||
}
|
||||
|
||||
// user is request locking, lets see if we can apply locking directly to the SQL...
|
||||
if ( dialect.useFollowOnLocking() ) {
|
||||
// Dialect prefers to perform locking in a separate step
|
||||
LOG.usingFollowOnLocking();
|
||||
final LockOptions lockOptionsToUse = new LockOptions();
|
||||
lockOptionsToUse.setLockMode( lockOptions.getEffectiveLockMode( "this_" ) );
|
||||
lockOptionsToUse.setTimeOut( lockOptions.getTimeOut() );
|
||||
lockOptionsToUse.setScope( lockOptions.getScope() );
|
||||
|
||||
// some dialects wont allow locking with paging...
|
||||
final RowSelection rowSelection = parameters.getRowSelection();
|
||||
final LimitHandler limitHandler = dialect.buildLimitHandler( sql, rowSelection );
|
||||
if ( LimitHelper.useLimit( limitHandler, rowSelection ) ) {
|
||||
// user has requested a combination of paging and locking. See if the dialect supports that
|
||||
// (ahem, Oracle...)
|
||||
if ( ! dialect.supportsLockingAndPaging() ) {
|
||||
LOG.delayedLockingDueToPaging();
|
||||
|
||||
// this one is kind of ugly. currently we do not track the needed alias-to-entity
|
||||
// mapping into the "hydratedEntities" which drives these callbacks
|
||||
// so for now apply the root lock mode to all. The root lock mode is listed in
|
||||
// the alias specific map under the alias "this_"...
|
||||
final LockOptions lockOptionsToUse = new LockOptions();
|
||||
lockOptionsToUse.setLockMode( lockOptions.getEffectiveLockMode( "this_" ) );
|
||||
lockOptionsToUse.setTimeOut( lockOptions.getTimeOut() );
|
||||
lockOptionsToUse.setScope( lockOptions.getScope() );
|
||||
|
||||
afterLoadActions.add(
|
||||
new AfterLoadAction() {
|
||||
@Override
|
||||
public void afterLoad(SessionImplementor session, Object entity, Loadable persister) {
|
||||
( (Session) session ).buildLockRequest( lockOptionsToUse )
|
||||
.lock( persister.getEntityName(), entity );
|
||||
}
|
||||
afterLoadActions.add(
|
||||
new AfterLoadAction() {
|
||||
@Override
|
||||
public void afterLoad(SessionImplementor session, Object entity, Loadable persister) {
|
||||
( (Session) session ).buildLockRequest( lockOptionsToUse )
|
||||
.lock( persister.getEntityName(), entity );
|
||||
}
|
||||
);
|
||||
parameters.setLockOptions( new LockOptions() );
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
);
|
||||
parameters.setLockOptions( new LockOptions() );
|
||||
return sql;
|
||||
}
|
||||
|
||||
// there are other conditions we might want to add here, such as checking the result types etc
|
||||
// but those are better served after we have redone the SQL generation to use ASTs.
|
||||
|
||||
final LockOptions locks = new LockOptions(lockOptions.getLockMode());
|
||||
locks.setScope( lockOptions.getScope());
|
||||
locks.setTimeOut( lockOptions.getTimeOut());
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.loader.hql;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
@ -39,12 +38,8 @@ import org.hibernate.LockMode;
|
|||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.pagination.LimitHandler;
|
||||
import org.hibernate.dialect.pagination.LimitHelper;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.engine.spi.RowSelection;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
|
@ -334,7 +329,7 @@ public class QueryLoader extends BasicLoader {
|
|||
// user is request locking, lets see if we can apply locking directly to the SQL...
|
||||
|
||||
// some dialects wont allow locking with paging...
|
||||
if ( shouldDelayLockingDueToPaging( sql, parameters, dialect, afterLoadActions ) ) {
|
||||
if ( shouldUseFollowOnLocking( parameters, dialect, afterLoadActions ) ) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue