HHH-17949 Fix upsert handling when optimistic locking is involved
This commit is contained in:
parent
0ce4f3c083
commit
8436326fc5
|
@ -191,6 +191,7 @@ public class SqlAstTranslatorWithUpsert<T extends JdbcOperation> extends Abstrac
|
|||
|
||||
protected void renderMergeUpdate(OptionalTableUpdate optionalTableUpdate) {
|
||||
final List<ColumnValueBinding> valueBindings = optionalTableUpdate.getValueBindings();
|
||||
final List<ColumnValueBinding> optimisticLockBindings = optionalTableUpdate.getOptimisticLockBindings();
|
||||
|
||||
appendSql( " when matched then update set " );
|
||||
for ( int i = 0; i < valueBindings.size(); i++ ) {
|
||||
|
@ -202,5 +203,21 @@ public class SqlAstTranslatorWithUpsert<T extends JdbcOperation> extends Abstrac
|
|||
appendSql( "=" );
|
||||
binding.getColumnReference().appendColumnForWrite( this, "s" );
|
||||
}
|
||||
renderMatchedWhere( optimisticLockBindings );
|
||||
}
|
||||
|
||||
private void renderMatchedWhere(List<ColumnValueBinding> optimisticLockBindings) {
|
||||
if ( !optimisticLockBindings.isEmpty() ) {
|
||||
appendSql( " where " );
|
||||
for (int i = 0; i < optimisticLockBindings.size(); i++) {
|
||||
final ColumnValueBinding binding = optimisticLockBindings.get( i );
|
||||
if ( i>0 ) {
|
||||
appendSql(" and ");
|
||||
}
|
||||
binding.getColumnReference().appendColumnForWrite( this, "t" );
|
||||
appendSql("=");
|
||||
binding.getValueExpression().accept( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -386,7 +386,9 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
|
|||
|
||||
final BindingGroup bindingGroup = jdbcValueBindings.getBindingGroup( tableMapping.getTableName() );
|
||||
if ( bindingGroup != null ) {
|
||||
bindingGroup.forEachBinding( (binding) -> {
|
||||
bindingGroup.forEachBinding( binding -> {
|
||||
// Skip parameter bindings for e.g. optimistic version check
|
||||
if ( binding.getPosition() <= jdbcInsert.getParameterBinders().size() ) {
|
||||
try {
|
||||
binding.getValueBinder().bind(
|
||||
insertStatement,
|
||||
|
@ -402,6 +404,7 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
|
|||
jdbcInsert.getSqlString()
|
||||
);
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,7 @@ package org.hibernate.orm.test.stateless;
|
|||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Version;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -17,9 +13,6 @@ import static org.junit.Assert.assertEquals;
|
|||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = UpsertVersionedTest.Record.class)
|
||||
public class UpsertVersionedTest {
|
||||
@RequiresDialect(H2Dialect.class)
|
||||
@RequiresDialect(SQLServerDialect.class)
|
||||
@RequiresDialect(value = PostgreSQLDialect.class, matchSubTypes = false)
|
||||
@Test void test(SessionFactoryScope scope) {
|
||||
scope.inStatelessTransaction(s-> {
|
||||
s.upsert(new Record(123L,null,"hello earth"));
|
||||
|
@ -30,21 +23,21 @@ public class UpsertVersionedTest {
|
|||
assertEquals("hello mars",s.get(Record.class,456L).message);
|
||||
});
|
||||
scope.inStatelessTransaction(s-> {
|
||||
s.upsert(new Record(123L,1L,"goodbye earth"));
|
||||
s.upsert(new Record(123L,0L,"goodbye earth"));
|
||||
});
|
||||
scope.inStatelessTransaction(s-> {
|
||||
assertEquals("goodbye earth",s.get(Record.class,123L).message);
|
||||
assertEquals("hello mars",s.get(Record.class,456L).message);
|
||||
});
|
||||
scope.inStatelessTransaction(s-> {
|
||||
s.upsert(new Record(456L,4L,"goodbye mars"));
|
||||
s.upsert(new Record(456L,3L,"goodbye mars"));
|
||||
});
|
||||
scope.inStatelessTransaction(s-> {
|
||||
assertEquals("goodbye earth",s.get(Record.class,123L).message);
|
||||
assertEquals("goodbye mars",s.get(Record.class,456L).message);
|
||||
});
|
||||
}
|
||||
@Entity
|
||||
@Entity(name = "Record")
|
||||
static class Record {
|
||||
@Id Long id;
|
||||
@Version Long version;
|
||||
|
|
Loading…
Reference in New Issue