Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.sql.ast.spi.ParameterMarkerStrategy;
import org.hibernate.sql.exec.internal.JdbcSelectWithActions;
import org.hibernate.sql.exec.spi.JdbcSelectWithActionsBuilder;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducerProvider;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.generator.Generator;
Expand Down Expand Up @@ -315,4 +317,9 @@ default <T> RootGraphImplementor<T> createEntityGraph(Class<T> entityType) {
*/
String bestGuessEntityName(Object object);

@Incubating
default JdbcSelectWithActionsBuilder getJdbcSelectWithActionsBuilder(){
return new JdbcSelectWithActions.Builder();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2201,7 +2201,8 @@ protected LockingStrategy generateLocker(LockMode lockMode, Locking.Scope lockSc
return getDialect().getLockingStrategy( this, lockMode, lockScope );
}

private LockingStrategy getLocker(LockMode lockMode, Locking.Scope lockScope) {
// Used by Hibernate Reactive
protected LockingStrategy getLocker(LockMode lockMode, Locking.Scope lockScope) {
return lockScope != Locking.Scope.ROOT_ONLY
// be sure to not use the cached form if any form of extended locking is requested
? generateLocker( lockMode, lockScope )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
import org.hibernate.dialect.SelectItemReferenceStrategy;
import org.hibernate.dialect.lock.spi.LockTimeoutType;
import org.hibernate.dialect.lock.spi.LockingSupport;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.jdbc.spi.JdbcServices;
Expand Down Expand Up @@ -177,11 +176,7 @@
import org.hibernate.sql.exec.internal.JdbcOperationQuerySelect;
import org.hibernate.sql.exec.internal.JdbcOperationQueryUpdate;
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
import org.hibernate.sql.exec.internal.JdbcSelectWithActions;
import org.hibernate.sql.exec.internal.LockTimeoutHandler;
import org.hibernate.sql.exec.internal.SqlTypedMappingJdbcParameter;
import org.hibernate.sql.exec.internal.lock.CollectionLockingAction;
import org.hibernate.sql.exec.internal.lock.FollowOnLockingAction;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcLockStrategy;
import org.hibernate.sql.exec.spi.JdbcOperation;
Expand Down Expand Up @@ -893,26 +888,17 @@ protected JdbcSelect translateSelect(SelectStatement selectStatement) {

final LockingSupport lockingSupport = getDialect().getLockingSupport();
final LockingSupport.Metadata lockingSupportMetadata = lockingSupport.getMetadata();

final JdbcSelectWithActions.Builder builder = new JdbcSelectWithActions.Builder( jdbcSelect );

final LockTimeoutType lockTimeoutType = lockingSupportMetadata.getLockTimeoutType( lockOptions.getTimeout() );
if ( lockTimeoutType == LockTimeoutType.CONNECTION ) {
builder.addSecondaryActionPair( new LockTimeoutHandler(
lockOptions.getTimeout(),
lockingSupport.getConnectionLockTimeoutStrategy()
) );
}

final LockStrategy lockStrategy = determineLockingStrategy( lockingTarget, lockOptions.getFollowOnStrategy() );
if ( lockStrategy == LockStrategy.FOLLOW_ON ) {
FollowOnLockingAction.apply( lockOptions, lockingTarget, lockingClauseStrategy, builder );
}
else if ( lockOptions.getScope() == Locking.Scope.INCLUDE_COLLECTIONS ) {
CollectionLockingAction.apply( lockOptions, lockingTarget, builder );
}

return builder.build();
return getSessionFactory().getJdbcSelectWithActionsBuilder()
.setPrimaryAction( jdbcSelect )
.setLockTimeoutType( lockingSupportMetadata.getLockTimeoutType( lockOptions.getTimeout() ) )
.setLockingSupport( lockingSupport )
.setLockOptions( lockOptions )
.setLockingTarget( lockingTarget )
.setLockingClauseStrategy( lockingClauseStrategy )
.setIsFollowOnLockStrategy( lockStrategy == LockStrategy.FOLLOW_ON )
.build();
}

private JdbcValuesMappingProducer buildJdbcValuesMappingProducer(SelectStatement selectStatement) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,25 @@
package org.hibernate.sql.exec.internal;

import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.LockOptions;
import org.hibernate.Locking;
import org.hibernate.dialect.lock.spi.LockTimeoutType;
import org.hibernate.dialect.lock.spi.LockingSupport;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.sql.ast.spi.LockingClauseStrategy;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.exec.internal.lock.CollectionLockingAction;
import org.hibernate.sql.exec.internal.lock.FollowOnLockingAction;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcLockStrategy;
import org.hibernate.sql.exec.spi.JdbcOperationQuery;
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
import org.hibernate.sql.exec.spi.JdbcParameterBinding;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.exec.spi.JdbcSelectWithActionsBuilder;
import org.hibernate.sql.exec.spi.LoadedValuesCollector;
import org.hibernate.sql.exec.spi.PostAction;
import org.hibernate.sql.exec.spi.PreAction;
Expand All @@ -35,9 +44,12 @@
public class JdbcSelectWithActions implements JdbcOperationQuery, JdbcSelect {
private final JdbcOperationQuerySelect primaryOperation;

private final LoadedValuesCollector loadedValuesCollector;
private final PreAction[] preActions;
private final PostAction[] postActions;
// Used by Hibernate Reactive
protected final LoadedValuesCollector loadedValuesCollector;
// Used by Hibernate Reactive
protected final PreAction[] preActions;
// Used by Hibernate Reactive
protected final PostAction[] postActions;

public JdbcSelectWithActions(
JdbcOperationQuerySelect primaryOperation,
Expand Down Expand Up @@ -149,24 +161,84 @@ public boolean isCompatibleWith(JdbcParameterBindings jdbcParameterBindings, Que
return primaryOperation.isCompatibleWith( jdbcParameterBindings, queryOptions );
}

public static class Builder {
private final JdbcOperationQuerySelect primaryAction;

public static class Builder implements JdbcSelectWithActionsBuilder {
private JdbcOperationQuerySelect primaryAction;
private LoadedValuesCollector loadedValuesCollector;
protected List<PreAction> preActions;
protected List<PostAction> postActions;

public Builder(JdbcOperationQuerySelect primaryAction) {
this.primaryAction = primaryAction;
protected LockTimeoutType lockTimeoutType;
protected LockingSupport lockingSupport;
protected LockOptions lockOptions;
protected QuerySpec lockingTarget;
protected LockingClauseStrategy lockingClauseStrategy;
boolean isFollonOnLockStrategy;

@Override
public Builder setPrimaryAction(JdbcSelect primaryAction){
assert primaryAction instanceof JdbcOperationQuerySelect;
this.primaryAction = (JdbcOperationQuerySelect) primaryAction;
return this;
}

@SuppressWarnings("UnusedReturnValue")
@Override
public Builder setLoadedValuesCollector(LoadedValuesCollector loadedValuesCollector) {
this.loadedValuesCollector = loadedValuesCollector;
return this;
}

@Override
public Builder setLockTimeoutType(LockTimeoutType lockTimeoutType){
this.lockTimeoutType = lockTimeoutType;
return this;
}

@Override
public Builder setLockingSupport(LockingSupport lockingSupport){
this.lockingSupport = lockingSupport;
return this;
}

@Override
public Builder setLockOptions(LockOptions lockOptions){
this.lockOptions = lockOptions;
return this;
}

@Override
public Builder setLockingTarget(QuerySpec lockingTarget){
this.lockingTarget = lockingTarget;
return this;
}

@Override
public Builder setLockingClauseStrategy(LockingClauseStrategy lockingClauseStrategy){
this.lockingClauseStrategy = lockingClauseStrategy;
return this;
}

@Override
public Builder setIsFollowOnLockStrategy(boolean isFollonOnLockStrategy){
this.isFollonOnLockStrategy = isFollonOnLockStrategy;
return this;
}

@Override
public JdbcSelect build() {
if ( lockTimeoutType == LockTimeoutType.CONNECTION ) {
addSecondaryActionPair(
new LockTimeoutHandler(
lockOptions.getTimeout(),
lockingSupport.getConnectionLockTimeoutStrategy()
)
);
}
if ( isFollonOnLockStrategy ) {
FollowOnLockingAction.apply( lockOptions, lockingTarget, lockingClauseStrategy, this );
}
else if ( lockOptions.getScope() == Locking.Scope.INCLUDE_COLLECTIONS ) {
CollectionLockingAction.apply( lockOptions, lockingTarget, this );
}
if ( preActions == null && postActions == null ) {
assert loadedValuesCollector == null;
return primaryAction;
Expand All @@ -182,6 +254,7 @@ public JdbcSelect build() {
*
* @return {@code this}, for method chaining.
*/
@Override
public Builder appendPreAction(PreAction... actions) {
if ( preActions == null ) {
preActions = new ArrayList<>();
Expand All @@ -195,6 +268,7 @@ public Builder appendPreAction(PreAction... actions) {
*
* @return {@code this}, for method chaining.
*/
@Override
public Builder prependPreAction(PreAction... actions) {
if ( preActions == null ) {
preActions = new ArrayList<>();
Expand All @@ -209,6 +283,7 @@ public Builder prependPreAction(PreAction... actions) {
*
* @return {@code this}, for method chaining.
*/
@Override
public Builder appendPostAction(PostAction... actions) {
if ( postActions == null ) {
postActions = new ArrayList<>();
Expand All @@ -222,6 +297,7 @@ public Builder appendPostAction(PostAction... actions) {
*
* @return {@code this}, for method chaining.
*/
@Override
public Builder prependPostAction(PostAction... actions) {
if ( postActions == null ) {
postActions = new ArrayList<>();
Expand All @@ -243,6 +319,7 @@ public Builder prependPostAction(PostAction... actions) {
*
* @return {@code this}, for method chaining.
*/
@Override
public Builder addSecondaryActionPair(SecondaryAction action) {
return addSecondaryActionPair( (PreAction) action, (PostAction) action );
}
Expand All @@ -255,24 +332,27 @@ public Builder addSecondaryActionPair(SecondaryAction action) {
*
* @return {@code this}, for method chaining.
*/
@Override
public Builder addSecondaryActionPair(PreAction preAction, PostAction postAction) {
prependPreAction( preAction );
appendPostAction( postAction );
return this;
}

private static PreAction[] toPreActionArray(List<PreAction> actions) {
if ( CollectionHelper.isEmpty( actions ) ) {
return null;
}
return actions.toArray( new PreAction[0] );
// Used by Hibernate Reactive
static PreAction[] toPreActionArray(List<PreAction> actions) {
if ( CollectionHelper.isEmpty( actions ) ) {
return null;
}

private static PostAction[] toPostActionArray(List<PostAction> actions) {
if ( CollectionHelper.isEmpty( actions ) ) {
return null;
}
return actions.toArray( new PostAction[0] );
return actions.toArray( new PreAction[0] );
}
// Used by Hibernate Reactive
static PostAction[] toPostActionArray(List<PostAction> actions) {
if ( CollectionHelper.isEmpty( actions ) ) {
return null;
}
return actions.toArray( new PostAction[0] );
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import org.hibernate.sql.ast.tree.from.FromClause;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.exec.internal.JdbcSelectWithActions;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcSelectWithActionsBuilder;
import org.hibernate.sql.exec.spi.LoadedValuesCollector;
import org.hibernate.sql.exec.spi.PostAction;
import org.hibernate.sql.exec.spi.StatementAccess;
Expand All @@ -40,11 +40,15 @@
* @author Steve Ebersole
*/
public class CollectionLockingAction implements PostAction {
private final LoadedValuesCollectorImpl loadedValuesCollector;
private final LockMode lockMode;
private final Timeout lockTimeout;

private CollectionLockingAction(
// Used by Hibernate Reactive
protected final LoadedValuesCollectorImpl loadedValuesCollector;
// Used by Hibernate Reactive
protected final LockMode lockMode;
// Used by Hibernate Reactive
protected final Timeout lockTimeout;

// Used by Hibernate Reactive
protected CollectionLockingAction(
LoadedValuesCollectorImpl loadedValuesCollector,
LockMode lockMode,
Timeout lockTimeout) {
Expand All @@ -56,7 +60,7 @@ private CollectionLockingAction(
public static void apply(
LockOptions lockOptions,
QuerySpec lockingTarget,
JdbcSelectWithActions.Builder jdbcSelectBuilder) {
JdbcSelectWithActionsBuilder jdbcSelectBuilder) {
assert lockOptions.getScope() == Locking.Scope.INCLUDE_COLLECTIONS;

final var loadedValuesCollector = resolveLoadedValuesCollector( lockingTarget.getFromClause() );
Expand All @@ -78,6 +82,11 @@ public void performPostAction(
StatementAccess jdbcStatementAccess,
Connection jdbcConnection,
ExecutionContext executionContext) {
performPostAction( executionContext );
}

// Used by Hibernate Reactive
protected void performPostAction(ExecutionContext executionContext) {
LockingHelper.logLoadedValues( loadedValuesCollector );

final var session = executionContext.getSession();
Expand Down Expand Up @@ -130,7 +139,8 @@ public void performPostAction(
}
}

private static LoadedValuesCollectorImpl resolveLoadedValuesCollector(FromClause fromClause) {
// Used by Hibernate Reactive
protected static LoadedValuesCollectorImpl resolveLoadedValuesCollector(FromClause fromClause) {
final var fromClauseRoots = fromClause.getRoots();
if ( fromClauseRoots.size() == 1 ) {
return new LoadedValuesCollectorImpl(
Expand All @@ -144,7 +154,8 @@ private static LoadedValuesCollectorImpl resolveLoadedValuesCollector(FromClause
}
}

private static Map<EntityMappingType, List<EntityKey>> segmentLoadedValues(LoadedValuesCollector loadedValuesCollector) {
// Used by Hibernate Reactive
protected static Map<EntityMappingType, List<EntityKey>> segmentLoadedValues(LoadedValuesCollector loadedValuesCollector) {
final Map<EntityMappingType, List<EntityKey>> map = new IdentityHashMap<>();
LockingHelper.segmentLoadedValues( loadedValuesCollector.getCollectedRootEntities(), map );
LockingHelper.segmentLoadedValues( loadedValuesCollector.getCollectedNonRootEntities(), map );
Expand All @@ -155,7 +166,8 @@ private static Map<EntityMappingType, List<EntityKey>> segmentLoadedValues(Loade
return map;
}

private static class LoadedValuesCollectorImpl implements LoadedValuesCollector {
// Used by Hibernate Reactive
protected static class LoadedValuesCollectorImpl implements LoadedValuesCollector {
private final List<NavigablePath> rootPaths;

private List<LoadedEntityRegistration> rootEntitiesToLock;
Expand Down
Loading