Skip to content
Open
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 @@ -221,7 +221,7 @@ public <R> SelectionQuery<R> createNativeQuery(String queryString, ResultSetMapp

@Override
public <T> Uni<T> find(Class<T> entityClass, Object primaryKey) {
return uni( () -> delegate.reactiveFind( entityClass, primaryKey, null, null ) );
return uni( () -> delegate.reactiveFind( entityClass, primaryKey ) );
}

@Override
Expand All @@ -236,7 +236,7 @@ public <T> Uni<T> find(Class<T> entityClass, Identifier<T> id) {

@Override
public <T> Uni<T> find(Class<T> entityClass, Object primaryKey, LockMode lockMode) {
return uni( () -> delegate.reactiveFind( entityClass, primaryKey, new LockOptions( lockMode ), null ) );
return uni( () -> delegate.reactiveFind( entityClass, primaryKey, lockMode, null ) );
}

@Override
Expand All @@ -252,7 +252,7 @@ public <T> Uni<T> find(Class<T> entityClass, Object primaryKey, LockOptions lock
@Override
public <T> Uni<T> find(EntityGraph<T> entityGraph, Object id) {
Class<T> entityClass = ( (RootGraph<T>) entityGraph ).getGraphedType().getJavaType();
return uni( () -> delegate.reactiveFind( entityClass, id, null, entityGraph ) );
return uni( () -> delegate.reactiveFind( entityClass, id, (LockMode) null, entityGraph ) );
}

@Override
Expand Down Expand Up @@ -297,7 +297,7 @@ public Uni<Void> refresh(Object entity) {

@Override
public Uni<Void> refresh(Object entity, LockMode lockMode) {
return uni( () -> delegate.reactiveRefresh( entity, new LockOptions( lockMode ) ) );
return uni( () -> delegate.reactiveRefresh( entity, lockMode ) );
}

@Override
Expand All @@ -317,7 +317,7 @@ public Uni<Void> refreshAll(Object... entity) {

@Override
public Uni<Void> lock(Object entity, LockMode lockMode) {
return uni( () -> delegate.reactiveLock( entity, new LockOptions( lockMode ) ) );
return uni( () -> delegate.reactiveLock( entity, lockMode ) );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,33 @@ public interface ReactiveSession extends ReactiveQueryProducer, ReactiveSharedSe

CompletionStage<Void> reactiveRefresh(Object entity, LockOptions lockMode);

default CompletionStage<Void> reactiveRefresh(Object entity, LockMode lockMode) {
return reactiveRefresh( entity, new LockOptions( lockMode ) );
}

CompletionStage<Void> reactiveRefresh(Object child, RefreshContext refreshedAlready);

CompletionStage<Void> reactiveLock(Object entity, LockOptions lockMode);

default CompletionStage<Void> reactiveLock(Object entity, LockMode lockMode){
return reactiveLock( entity, new LockOptions(lockMode) );
}

CompletionStage<Void> reactiveLock(String entityName, Object entity, LockOptions lockMode);

<T> CompletionStage<T> reactiveGet(Class<T> entityClass, Object id);

<T> CompletionStage<T> reactiveFind(Class<T> entityClass, Object id, LockOptions lockOptions, EntityGraph<T> fetchGraph);

default <T> CompletionStage<T> reactiveFind(Class<T> entityClass, Object id){
return reactiveFind( entityClass, id, (LockOptions) null, null );
}

default <T> CompletionStage<T> reactiveFind(Class<T> entityClass, Object id, LockMode lockMode, EntityGraph<T> fetchGraph ){
return reactiveFind( entityClass, id, new LockOptions( lockMode ), fetchGraph );
}


<T> CompletionStage<List<T>> reactiveFind(Class<T> entityClass, Object... ids);

<T> CompletionStage<T> reactiveFind(Class<T> entityClass, Map<String,Object> naturalIds);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,11 @@ public CompletionStage<Void> reactiveRefresh(Object entity, LockOptions lockOpti
return fireRefresh( new RefreshEvent( entity, lockOptions, this ) );
}

@Override
public CompletionStage<Void> reactiveRefresh(Object entity, LockMode lockMode) {
return reactiveRefresh( entity, fromLockMode( lockMode ) );
}

@Override
public CompletionStage<Void> reactiveRefresh(Object object, RefreshContext refreshedAlready) {
checkOpenOrWaitingForAutoClose();
Expand Down Expand Up @@ -1193,6 +1198,11 @@ public CompletionStage<Void> reactiveLock(Object object, LockOptions lockOptions
return fireLock( new LockEvent( object, lockOptions, this ) );
}

@Override
public CompletionStage<Void> reactiveLock(Object entity, LockMode lockMode) {
return reactiveLock( entity, fromLockMode( lockMode ) );
}

@Override
public CompletionStage<Void> reactiveLock(String entityName, Object object, LockOptions lockOptions) {
checkOpen();
Expand Down Expand Up @@ -1254,6 +1264,11 @@ public <T> CompletionStage<T> reactiveFind(
} );
}

@Override
public <T> CompletionStage<T> reactiveFind(Class<T> entityClass, Object id, LockMode lockMode, EntityGraph<T> fetchGraph){
return reactiveFind( entityClass, id, fromLockMode( lockMode ), fetchGraph );
}

private <T> CompletionStage<T> handleReactiveFindException(
Class<T> entityClass,
Object primaryKey,
Expand Down Expand Up @@ -1318,7 +1333,7 @@ public <T> CompletionStage<T> reactiveFind(Class<T> entityClass, Map<String, Obj
final Object normalizedIdValues = persister.getNaturalIdMapping().normalizeInput( ids );
return new NaturalIdLoadAccessImpl<T>( this, persister, requireEntityPersister( entityClass ) )
.resolveNaturalId( normalizedIdValues )
.thenCompose( id -> reactiveFind( entityClass, id, null, null ) );
.thenCompose( id -> reactiveFind( entityClass, id ) );
}

private <T> ReactiveEntityPersister entityPersister(Class<T> entityClass) {
Expand Down Expand Up @@ -1811,4 +1826,9 @@ public <T> RootGraphImplementor<T> getEntityGraph(Class<T> entity, String name)
}
return (RootGraphImplementor<T>) entityGraph;
}

private LockOptions fromLockMode(LockMode lockMode) {
// the LockOptions(LockMode lockMode) constructor does not set the LockOptions#timeout value but we need to call setLockMode(LocMode)
return new LockOptions().setLockMode( lockMode );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public MutationQuery createMutationQuery(JpaCriteriaInsert<?> insert) {

@Override
public <T> CompletionStage<T> find(Class<T> entityClass, Object primaryKey) {
return delegate.reactiveFind( entityClass, primaryKey, null, null );
return delegate.reactiveFind( entityClass, primaryKey );
}

@Override
Expand All @@ -150,7 +150,7 @@ public <T> CompletionStage<T> find(Class<T> entityClass, Identifier<T> id) {

@Override
public <T> CompletionStage<T> find(Class<T> entityClass, Object primaryKey, LockMode lockMode) {
return delegate.reactiveFind( entityClass, primaryKey, new LockOptions( lockMode ), null );
return delegate.reactiveFind( entityClass, primaryKey, lockMode, null );
}

@Override
Expand All @@ -167,7 +167,7 @@ public <T> CompletionStage<T> find(Class<T> entityClass, Object primaryKey, Lock
@Override
public <T> CompletionStage<T> find(EntityGraph<T> entityGraph, Object id) {
Class<T> entityClass = ( (RootGraph<T>) entityGraph ).getGraphedType().getJavaType();
return delegate.reactiveFind( entityClass, id, null, entityGraph );
return delegate.reactiveFind( entityClass, id, (LockOptions) null, entityGraph );
}

@Override
Expand Down Expand Up @@ -212,7 +212,7 @@ public CompletionStage<Void> refresh(Object entity) {

@Override
public CompletionStage<Void> refresh(Object entity, LockMode lockMode) {
return delegate.reactiveRefresh( entity, new LockOptions(lockMode) );
return delegate.reactiveRefresh( entity, lockMode );
}

@Override
Expand All @@ -232,7 +232,7 @@ public CompletionStage<Void> refresh(Object... entity) {

@Override
public CompletionStage<Void> lock(Object entity, LockMode lockMode) {
return delegate.reactiveLock( entity, new LockOptions(lockMode) );
return delegate.reactiveLock( entity, lockMode );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@
*/
package org.hibernate.reactive;

import org.hibernate.LockMode;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.reactive.containers.DatabaseConfiguration;
import org.hibernate.reactive.testing.SqlStatementTracker;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import io.vertx.junit5.Timeout;
Expand All @@ -22,11 +29,44 @@
import jakarta.persistence.OneToMany;

import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.reactive.containers.DatabaseConfiguration.dbType;

@Timeout(value = 10, timeUnit = TimeUnit.MINUTES)
public class FindByIdWithLockTest extends BaseReactiveTest {
private static final Long CHILD_ID = 1L;

private static SqlStatementTracker sqlTracker;

@Override
protected Configuration constructConfiguration() {
Configuration configuration = super.constructConfiguration();

// Construct a tracker that collects query statements via the SqlStatementLogger framework.
// Pass in configuration properties to hand off any actual logging properties
sqlTracker = new SqlStatementTracker( FindByIdWithLockTest::filter, configuration.getProperties() );
return configuration;
}

@BeforeEach
public void clearTracker() {
sqlTracker.clear();
}

protected void addServices(StandardServiceRegistryBuilder builder) {

Check notice

Code scanning / CodeQL

Missing Override annotation Note test

This method overrides
BaseReactiveTest.addServices
; it is advisable to add an Override annotation.
sqlTracker.registerService( builder );
}

private static boolean filter(String s) {
String[] accepted = { "select " };
for ( String valid : accepted ) {
if ( s.toLowerCase().startsWith( valid ) ) {
return true;
}
}
return false;
}


@Override
protected Collection<Class<?>> annotatedEntities() {
return List.of( Parent.class, Child.class );
Expand All @@ -50,6 +90,43 @@
);
}

@Test
public void testFindUpgradeNoWait(VertxTestContext context) {
Child child = new Child( CHILD_ID, "And" );
test(
context, getMutinySessionFactory()
.withTransaction( session -> session.persistAll( child ) )
.invoke( () -> sqlTracker.clear() )
.chain( () -> getMutinySessionFactory().withTransaction( session -> session
.find( Child.class, CHILD_ID, LockMode.UPGRADE_NOWAIT )
.invoke( c -> {
assertThat( c ).isNotNull();
assertThat( c.getId() ).isEqualTo( CHILD_ID );
String selectQuery = sqlTracker.getLoggedQueries().get( 0 );
assertThat( sqlTracker.getLoggedQueries() ).hasSize( 1 );
switch ( DatabaseConfiguration.dbType() ) {
case POSTGRESQL -> assertThat( selectQuery )
.endsWith( "for no key update of c1_0 nowait" );
case COCKROACHDB -> assertThat( selectQuery )
.endsWith( "for update of c1_0 nowait" );
case SQLSERVER -> assertThat( selectQuery )
.contains( "with (updlock,holdlock,rowlock,nowait)" );
case ORACLE -> assertThat( selectQuery )
.contains( "for update of c1_0.id nowait" );
case DB2 -> assertThat( selectQuery )
.contains( "for read only with rs use and keep update locks" ); // DB2 does not support nowait
case MARIA -> assertThat( selectQuery )
.contains( "for update nowait" );
case MYSQL -> assertThat( selectQuery )
.contains( "for update of c1_0 nowait" );
default -> throw new IllegalArgumentException( "Database not recognized: " + dbType().name() );
}
}
) ) )
);
}


@Entity(name = "Parent")
public static class Parent {

Expand Down
Loading