HHH-15393 - Improve write-paths to use mapping model

This commit is contained in:
Steve Ebersole 2022-11-30 12:59:31 -06:00
parent 175fe0e44d
commit c04caa18de
19 changed files with 290 additions and 94 deletions

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.persister.collection; package org.hibernate.persister.collection;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -390,10 +389,10 @@ public class OneToManyPersister extends AbstractCollectionPersister {
return new TableUpdateStandard( return new TableUpdateStandard(
tableReference, tableReference,
this, this,
parameters,
valueBindings, valueBindings,
keyRestrictionBindings, keyRestrictionBindings,
Collections.emptyList(), null,
parameters,
sqlWhereString sqlWhereString
); );
} }

View File

@ -178,6 +178,7 @@ import org.hibernate.sql.exec.spi.JdbcOperationQueryUpdate;
import org.hibernate.sql.exec.spi.JdbcParameterBinder; import org.hibernate.sql.exec.spi.JdbcParameterBinder;
import org.hibernate.sql.exec.spi.JdbcParameterBinding; import org.hibernate.sql.exec.spi.JdbcParameterBinding;
import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.model.ast.ColumnValueParameter;
import org.hibernate.sql.model.ast.ColumnWriteFragment; import org.hibernate.sql.model.ast.ColumnWriteFragment;
import org.hibernate.sql.model.ast.TableMutation; import org.hibernate.sql.model.ast.TableMutation;
import org.hibernate.sql.model.internal.TableDeleteCustomSql; import org.hibernate.sql.model.internal.TableDeleteCustomSql;
@ -615,6 +616,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
this.limitParameter = limitParameter; this.limitParameter = limitParameter;
} }
@SuppressWarnings("unchecked")
protected <R> R interpretExpression(Expression expression, JdbcParameterBindings jdbcParameterBindings) { protected <R> R interpretExpression(Expression expression, JdbcParameterBindings jdbcParameterBindings) {
if ( expression instanceof Literal ) { if ( expression instanceof Literal ) {
return (R) ( (Literal) expression ).getLiteralValue(); return (R) ( (Literal) expression ).getLiteralValue();
@ -766,6 +768,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
} }
} }
//noinspection unchecked
return (T) jdbcOperation; return (T) jdbcOperation;
} }
finally { finally {
@ -902,6 +905,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
int startPosition, int startPosition,
JdbcParameterBindings jdbcParamBindings, JdbcParameterBindings jdbcParamBindings,
ExecutionContext executionContext) throws SQLException { ExecutionContext executionContext) throws SQLException {
//noinspection unchecked
getJdbcMapping().getJdbcValueBinder().bind( getJdbcMapping().getJdbcValueBinder().bind(
statement, statement,
executionContext.getQueryOptions().getLimit().getFirstRow(), executionContext.getQueryOptions().getLimit().getFirstRow(),
@ -923,6 +927,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
int startPosition, int startPosition,
JdbcParameterBindings jdbcParamBindings, JdbcParameterBindings jdbcParamBindings,
ExecutionContext executionContext) throws SQLException { ExecutionContext executionContext) throws SQLException {
//noinspection unchecked
getJdbcMapping().getJdbcValueBinder().bind( getJdbcMapping().getJdbcValueBinder().bind(
statement, statement,
executionContext.getQueryOptions().getLimit().getMaxRows(), executionContext.getQueryOptions().getLimit().getMaxRows(),
@ -1288,7 +1293,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
private enum LockKind { private enum LockKind {
NONE, NONE,
SHARE, SHARE,
UPDATE; UPDATE
} }
protected String getForUpdate() { protected String getForUpdate() {
@ -1625,12 +1630,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
if ( cte.getCteTable().getCteColumns() == null ) { if ( cte.getCteTable().getCteColumns() == null ) {
final List<String> columnExpressions = new ArrayList<>(); final List<String> columnExpressions = new ArrayList<>();
cte.getCteTable().getTableGroupProducer().visitSubParts( cte.getCteTable().getTableGroupProducer().visitSubParts(
modelPart -> { modelPart -> modelPart.forEachSelectable(
modelPart.forEachSelectable(
0, 0,
(index, mapping) -> columnExpressions.add( mapping.getSelectionExpression() ) (index, mapping) -> columnExpressions.add( mapping.getSelectionExpression() )
); ),
},
null null
); );
for ( String columnExpression : columnExpressions ) { for ( String columnExpression : columnExpressions ) {
@ -4013,6 +4016,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
throw new ExecutionException( "JDBC parameter value not bound - " + offsetParameter ); throw new ExecutionException( "JDBC parameter value not bound - " + offsetParameter );
} }
final Number bindValue = (Number) binding.getBindValue(); final Number bindValue = (Number) binding.getBindValue();
//noinspection unchecked
offsetParameter.getExpressionType().getJdbcMappings().get( 0 ).getJdbcValueBinder().bind( offsetParameter.getExpressionType().getJdbcMappings().get( 0 ).getJdbcValueBinder().bind(
statement, statement,
bindValue.intValue() + offsetValue, bindValue.intValue() + offsetValue,
@ -4092,6 +4096,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
offsetValue = dynamicOffset.intValue() + staticOffset; offsetValue = dynamicOffset.intValue() + staticOffset;
dynamicOffset = null; dynamicOffset = null;
} }
//noinspection unchecked
fetchParameter.getExpressionType().getJdbcMappings().get( 0 ).getJdbcValueBinder().bind( fetchParameter.getExpressionType().getJdbcMappings().get( 0 ).getJdbcValueBinder().bind(
statement, statement,
bindValue.intValue() + offsetValue, bindValue.intValue() + offsetValue,
@ -5062,7 +5067,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
assert literal.getExpressionType().getJdbcTypeCount() == 1; assert literal.getExpressionType().getJdbcTypeCount() == 1;
final JdbcMapping jdbcMapping = literal.getJdbcMapping(); final JdbcMapping jdbcMapping = literal.getJdbcMapping();
final JdbcLiteralFormatter literalFormatter = jdbcMapping.getJdbcLiteralFormatter(); final JdbcLiteralFormatter<Object> literalFormatter = jdbcMapping.getJdbcLiteralFormatter();
// If we encounter a plain literal in the select clause which has no literal formatter, we must render it as parameter // If we encounter a plain literal in the select clause which has no literal formatter, we must render it as parameter
if ( literalFormatter == null ) { if ( literalFormatter == null ) {
@ -6510,7 +6515,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
else { else {
assert jdbcParameter.getExpressionType().getJdbcTypeCount() == 1; assert jdbcParameter.getExpressionType().getJdbcTypeCount() == 1;
final JdbcMapping jdbcMapping = jdbcParameter.getExpressionType().getJdbcMappings().get( 0 ); final JdbcMapping jdbcMapping = jdbcParameter.getExpressionType().getJdbcMappings().get( 0 );
final JdbcLiteralFormatter literalFormatter = jdbcMapping.getJdbcLiteralFormatter(); //noinspection unchecked
final JdbcLiteralFormatter<Object> literalFormatter = jdbcMapping.getJdbcLiteralFormatter();
if ( literalFormatter == null ) { if ( literalFormatter == null ) {
throw new IllegalArgumentException( "Can't render parameter as literal, no literal formatter found" ); throw new IllegalArgumentException( "Can't render parameter as literal, no literal formatter found" );
} }
@ -7685,7 +7691,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
} }
/** /**
* Handle rendering an insert with no columns (eye roll) * Handle rendering an insert with no columns
*/ */
protected void renderInsertIntoNoColumns(TableInsertStandard tableInsert) { protected void renderInsertIntoNoColumns(TableInsertStandard tableInsert) {
renderIntoIntoAndTable( tableInsert ); renderIntoIntoAndTable( tableInsert );
@ -7697,10 +7703,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
assert sqlBuffer.toString().isEmpty(); assert sqlBuffer.toString().isEmpty();
sqlBuffer.append( tableInsert.getCustomSql() ); sqlBuffer.append( tableInsert.getCustomSql() );
tableInsert.getParameters().forEach( (parameter) -> { tableInsert.forEachParameter( this::applyParameter );
parameterBinders.add( parameter.getParameterBinder() );
jdbcParameters.addParameter( parameter );
} );
} }
@Override @Override
@ -7777,10 +7780,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
assert sqlBuffer.toString().isEmpty(); assert sqlBuffer.toString().isEmpty();
sqlBuffer.append( tableUpdate.getCustomSql() ); sqlBuffer.append( tableUpdate.getCustomSql() );
tableUpdate.getParameters().forEach( (parameter) -> { tableUpdate.forEachParameter( this::applyParameter );
parameterBinders.add( parameter.getParameterBinder() );
jdbcParameters.addParameter( parameter );
} );
} }
@Override @Override
@ -7838,10 +7838,13 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
assert sqlBuffer.toString().isEmpty(); assert sqlBuffer.toString().isEmpty();
sqlBuffer.append( tableDelete.getCustomSql() ); sqlBuffer.append( tableDelete.getCustomSql() );
tableDelete.getParameters().forEach( (parameter) -> { tableDelete.forEachParameter( this::applyParameter );
}
protected void applyParameter(ColumnValueParameter parameter) {
assert parameter != null;
parameterBinders.add( parameter.getParameterBinder() ); parameterBinders.add( parameter.getParameterBinder() );
jdbcParameters.addParameter( parameter ); jdbcParameters.addParameter( parameter );
} );
} }
@Override @Override

View File

@ -40,9 +40,7 @@ public abstract class AbstractRestrictedTableMutation<O extends MutationOperatio
@Override @Override
public void forEachKeyBinding(BiConsumer<Integer, ColumnValueBinding> consumer) { public void forEachKeyBinding(BiConsumer<Integer, ColumnValueBinding> consumer) {
for ( int i = 0; i < keyRestrictionBindings.size(); i++ ) { forEachThing( keyRestrictionBindings, consumer );
consumer.accept( i, keyRestrictionBindings.get( i ) );
}
} }
@Override @Override
@ -52,8 +50,6 @@ public abstract class AbstractRestrictedTableMutation<O extends MutationOperatio
@Override @Override
public void forEachOptimisticLockBinding(BiConsumer<Integer, ColumnValueBinding> consumer) { public void forEachOptimisticLockBinding(BiConsumer<Integer, ColumnValueBinding> consumer) {
for ( int i = 0; i < optLockRestrictionBindings.size(); i++ ) { forEachThing( optLockRestrictionBindings, consumer );
consumer.accept( i, optLockRestrictionBindings.get( i ) );
}
} }
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.sql.model.ast;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.hibernate.engine.jdbc.mutation.internal.MutationQueryOptions; import org.hibernate.engine.jdbc.mutation.internal.MutationQueryOptions;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -75,7 +76,21 @@ public abstract class AbstractTableMutation<O extends MutationOperation>
return parameters; return parameters;
} }
protected <T> void forEachThing(List<T> list, BiConsumer<Integer,T> action) { public void forEachParameter(Consumer<ColumnValueParameter> consumer) {
if ( parameters == null ) {
return;
}
for ( int i = 0; i < parameters.size(); i++ ) {
consumer.accept( parameters.get( i ) );
}
}
protected static <T> void forEachThing(List<T> list, BiConsumer<Integer,T> action) {
if ( list == null ) {
return;
}
for ( int i = 0; i < list.size(); i++ ) { for ( int i = 0; i < list.size(); i++ ) {
action.accept( i, list.get( i ) ); action.accept( i, list.get( i ) );
} }

View File

@ -6,8 +6,10 @@
*/ */
package org.hibernate.sql.model.ast; package org.hibernate.sql.model.ast;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
import org.hibernate.sql.exec.spi.JdbcParameterBinder; import org.hibernate.sql.exec.spi.JdbcParameterBinder;
@ -17,6 +19,8 @@ import org.hibernate.sql.model.TableMapping;
import org.hibernate.sql.model.jdbc.JdbcUpdateMutation; import org.hibernate.sql.model.jdbc.JdbcUpdateMutation;
/** /**
* Base support for TableUpdate implementations
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class AbstractTableUpdate<O extends MutationOperation> public abstract class AbstractTableUpdate<O extends MutationOperation>
@ -27,31 +31,60 @@ public abstract class AbstractTableUpdate<O extends MutationOperation>
public AbstractTableUpdate( public AbstractTableUpdate(
MutatingTableReference mutatingTable, MutatingTableReference mutatingTable,
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
List<ColumnValueParameter> parameters,
List<ColumnValueBinding> valueBindings, List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings, List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings) { List<ColumnValueBinding> optLockRestrictionBindings) {
this( super(
mutatingTable, mutatingTable,
mutationTarget, mutationTarget,
"update for " + mutationTarget.getRolePath(), "update for " + mutationTarget.getNavigableRole(),
parameters,
valueBindings,
keyRestrictionBindings, keyRestrictionBindings,
optLockRestrictionBindings optLockRestrictionBindings,
collectParameters( valueBindings, keyRestrictionBindings, optLockRestrictionBindings )
); );
this.valueBindings = valueBindings;
} }
public AbstractTableUpdate( public <T> AbstractTableUpdate(
MutatingTableReference mutatingTable, MutatingTableReference tableReference,
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
String sqlComment, List<ColumnValueBinding> valueBindings,
List<ColumnValueParameter> parameters, List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings,
List<ColumnValueParameter> parameters) {
super(
tableReference,
mutationTarget,
"update for " + mutationTarget.getNavigableRole(),
keyRestrictionBindings,
optLockRestrictionBindings,
parameters
);
this.valueBindings = valueBindings;
}
public static List<ColumnValueParameter> collectParameters(
List<ColumnValueBinding> valueBindings, List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings, List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings) { List<ColumnValueBinding> optLockRestrictionBindings) {
super( mutatingTable, mutationTarget, sqlComment, keyRestrictionBindings, optLockRestrictionBindings, parameters ); final List<ColumnValueParameter> params = new ArrayList<>();
this.valueBindings = valueBindings;
final BiConsumer<Integer,ColumnValueBinding> intermediateConsumer = (index, binding) -> {
final ColumnWriteFragment valueExpression = binding.getValueExpression();
if ( valueExpression != null ) {
final ColumnValueParameter parameter = valueExpression.getParameter();
if ( parameter != null ) {
params.add( parameter );
}
}
};
forEachThing( valueBindings, intermediateConsumer );
forEachThing( keyRestrictionBindings, intermediateConsumer );
forEachThing( optLockRestrictionBindings, intermediateConsumer );
return params;
} }
@Override @Override
@ -74,6 +107,20 @@ public abstract class AbstractTableUpdate<O extends MutationOperation>
forEachThing( valueBindings, consumer ); forEachThing( valueBindings, consumer );
} }
@Override
public void forEachParameter(Consumer<ColumnValueParameter> consumer) {
final BiConsumer<Integer,ColumnValueBinding> intermediateConsumer = (index, binding) -> {
final ColumnValueParameter parameter = binding.getValueExpression().getParameter();
if ( parameter != null ) {
consumer.accept( parameter );
}
};
forEachThing( getValueBindings(), intermediateConsumer );
forEachThing( getKeyBindings(), intermediateConsumer );
forEachThing( getOptimisticLockBindings(), intermediateConsumer );
}
@Override @Override
protected O createMutationOperation(TableMapping tableDetails, String sql, List<JdbcParameterBinder> effectiveBinders) { protected O createMutationOperation(TableMapping tableDetails, String sql, List<JdbcParameterBinder> effectiveBinders) {
//noinspection unchecked //noinspection unchecked

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.model.ast;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import org.hibernate.annotations.OptimisticLockType;
import org.hibernate.sql.model.MutationOperation; import org.hibernate.sql.model.MutationOperation;
/** /**
@ -19,20 +20,42 @@ import org.hibernate.sql.model.MutationOperation;
*/ */
public interface RestrictedTableMutation<O extends MutationOperation> public interface RestrictedTableMutation<O extends MutationOperation>
extends TableMutation<O> { extends TableMutation<O> {
/**
* The bindings for each key restriction (WHERE clause).
*/
List<ColumnValueBinding> getKeyBindings(); List<ColumnValueBinding> getKeyBindings();
/**
* The number of {@linkplain #getKeyBindings() key bindings}
*/
default int getNumberOfKeyBindings() { default int getNumberOfKeyBindings() {
return getKeyBindings().size(); return getKeyBindings().size();
} }
/**
* Visit each {@linkplain #getKeyBindings() key binding}
*/
void forEachKeyBinding(BiConsumer<Integer,ColumnValueBinding> consumer); void forEachKeyBinding(BiConsumer<Integer,ColumnValueBinding> consumer);
/**
* All optimistic-lock bindings (WHERE clause), appended after
* {@linkplain #getKeyBindings() key bindings}
*
* @see OptimisticLockType
*/
List<ColumnValueBinding> getOptimisticLockBindings(); List<ColumnValueBinding> getOptimisticLockBindings();
/**
* The number of {@linkplain #getOptimisticLockBindings() optimistic-lock bindings}
*/
default int getNumberOfOptimisticLockBindings() { default int getNumberOfOptimisticLockBindings() {
final List<ColumnValueBinding> bindings = getOptimisticLockBindings(); final List<ColumnValueBinding> bindings = getOptimisticLockBindings();
return bindings == null ? 0 : bindings.size(); return bindings == null ? 0 : bindings.size();
} }
/**
* Visit each {@linkplain #getOptimisticLockBindings() optimistic-lock binding}
*/
void forEachOptimisticLockBinding(BiConsumer<Integer,ColumnValueBinding> consumer); void forEachOptimisticLockBinding(BiConsumer<Integer,ColumnValueBinding> consumer);
} }

View File

@ -7,6 +7,7 @@
package org.hibernate.sql.model.ast; package org.hibernate.sql.model.ast;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
@ -24,6 +25,10 @@ import org.hibernate.sql.model.ValuesAnalysis;
* Acts as a factory for {@link org.hibernate.sql.model.MutationOperation} instances, * Acts as a factory for {@link org.hibernate.sql.model.MutationOperation} instances,
* which are the forms used to "perform" the mutation using JDBC. * which are the forms used to "perform" the mutation using JDBC.
* *
* @apiNote The parameter order returned from here is the expected order of binding
* to the {@link java.sql.PreparedStatement} - see {@link #getParameters()} and
* {@link #forEachParameter}
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface TableMutation<O extends MutationOperation> extends Statement { public interface TableMutation<O extends MutationOperation> extends Statement {
@ -57,11 +62,30 @@ public interface TableMutation<O extends MutationOperation> extends Statement {
Expectation getExpectation(); Expectation getExpectation();
/** /**
* The JDBC parameters associated with this mutation * The JDBC parameters associated with this mutation.
*
* The order here is the expected binding order for the
* {@link java.sql.PreparedStatement}.
*
* @see #forEachParameter
*/ */
List<ColumnValueParameter> getParameters(); List<ColumnValueParameter> getParameters();
/**
* Visit the JDBC parameters associated with this mutation.
*
* The order here is the expected binding order for the
* {@link java.sql.PreparedStatement}.
*
* @see #getParameters
*/
void forEachParameter(Consumer<ColumnValueParameter> consumer);
O createMutationOperation(ValuesAnalysis valuesAnalysis, SessionFactoryImplementor sessionFactory); O createMutationOperation(ValuesAnalysis valuesAnalysis, SessionFactoryImplementor sessionFactory);
/**
* A {@link org.hibernate.sql.ast.SqlAstTranslator} callback to create
* an appropriate mutation using the translated sql and parameter binders.
*/
O createMutationOperation(String sql, List<JdbcParameterBinder> parameterBinders); O createMutationOperation(String sql, List<JdbcParameterBinder> parameterBinders);
} }

View File

@ -15,6 +15,7 @@ import org.hibernate.sql.model.MutationTarget;
import org.hibernate.sql.model.MutationType; import org.hibernate.sql.model.MutationType;
import org.hibernate.sql.model.TableMapping; import org.hibernate.sql.model.TableMapping;
import org.hibernate.sql.model.ast.ColumnValueBinding; import org.hibernate.sql.model.ast.ColumnValueBinding;
import org.hibernate.sql.model.ast.ColumnValueParameter;
import org.hibernate.sql.model.ast.MutatingTableReference; import org.hibernate.sql.model.ast.MutatingTableReference;
import org.hibernate.sql.model.ast.TableInsert; import org.hibernate.sql.model.ast.TableInsert;
@ -30,15 +31,17 @@ public abstract class AbstractTableInsertBuilder
private final List<ColumnValueBinding> valueBindingList = new ArrayList<>(); private final List<ColumnValueBinding> valueBindingList = new ArrayList<>();
private List<ColumnValueBinding> lobValueBindingList; private List<ColumnValueBinding> lobValueBindingList;
private final List<ColumnValueParameter> parameters = new ArrayList<>();
public AbstractTableInsertBuilder( public AbstractTableInsertBuilder(
MutationTarget mutationTarget, MutationTarget<?> mutationTarget,
TableMapping table, TableMapping table,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
super( MutationType.INSERT, mutationTarget, table, sessionFactory ); super( MutationType.INSERT, mutationTarget, table, sessionFactory );
} }
public AbstractTableInsertBuilder( public AbstractTableInsertBuilder(
MutationTarget mutationTarget, MutationTarget<?> mutationTarget,
MutatingTableReference tableReference, MutatingTableReference tableReference,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
super( MutationType.INSERT, mutationTarget, tableReference, sessionFactory ); super( MutationType.INSERT, mutationTarget, tableReference, sessionFactory );
@ -56,6 +59,10 @@ public abstract class AbstractTableInsertBuilder
return lobValueBindingList; return lobValueBindingList;
} }
protected List<ColumnValueParameter> getParameters() {
return parameters;
}
@Override @Override
public void addValueColumn( public void addValueColumn(
String columnName, String columnName,
@ -81,4 +88,9 @@ public abstract class AbstractTableInsertBuilder
JdbcMapping jdbcMapping) { JdbcMapping jdbcMapping) {
addColumn( columnName, columnWriteFragment, jdbcMapping, keyBindingList ); addColumn( columnName, columnWriteFragment, jdbcMapping, keyBindingList );
} }
@Override
protected void handleParameterCreation(ColumnValueParameter parameter) {
parameters.add( parameter );
}
} }

View File

@ -36,9 +36,6 @@ public abstract class AbstractTableMutationBuilder<M extends TableMutation<?>> i
private final MutatingTableReference mutatingTable; private final MutatingTableReference mutatingTable;
private final List<ColumnValueParameter> parameters = new ArrayList<>();
public AbstractTableMutationBuilder( public AbstractTableMutationBuilder(
MutationType mutationType, MutationType mutationType,
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
@ -76,10 +73,6 @@ public abstract class AbstractTableMutationBuilder<M extends TableMutation<?>> i
return sessionFactory.getJdbcServices(); return sessionFactory.getJdbcServices();
} }
protected List<ColumnValueParameter> getParameters() {
return parameters;
}
protected void addColumn( protected void addColumn(
String columnName, String columnName,
String columnWriteFragment, String columnWriteFragment,
@ -116,7 +109,7 @@ public abstract class AbstractTableMutationBuilder<M extends TableMutation<?>> i
final ColumnValueParameter parameter; final ColumnValueParameter parameter;
if ( columnWriteFragment.contains( "?" ) ) { if ( columnWriteFragment.contains( "?" ) ) {
parameter = new ColumnValueParameter( columnReference, parameterUsage ); parameter = new ColumnValueParameter( columnReference, parameterUsage );
parameters.add( parameter ); handleParameterCreation( parameter );
} }
else { else {
parameter = null; parameter = null;
@ -125,6 +118,8 @@ public abstract class AbstractTableMutationBuilder<M extends TableMutation<?>> i
return new ColumnValueBinding( columnReference, new ColumnWriteFragment( columnWriteFragment, parameter, jdbcMapping ) ); return new ColumnValueBinding( columnReference, new ColumnWriteFragment( columnWriteFragment, parameter, jdbcMapping ) );
} }
protected abstract void handleParameterCreation(ColumnValueParameter parameter);
@SafeVarargs @SafeVarargs
protected final <T> List<T> combine(List<T> list1, List<T>... additionalLists) { protected final <T> List<T> combine(List<T> list1, List<T>... additionalLists) {
final ArrayList<T> combined = list1 == null final ArrayList<T> combined = list1 == null

View File

@ -18,8 +18,11 @@ import org.hibernate.sql.model.TableMapping;
import org.hibernate.sql.model.ast.ColumnValueBinding; import org.hibernate.sql.model.ast.ColumnValueBinding;
import org.hibernate.sql.model.ast.MutatingTableReference; import org.hibernate.sql.model.ast.MutatingTableReference;
import org.hibernate.sql.model.ast.RestrictedTableMutation; import org.hibernate.sql.model.ast.RestrictedTableMutation;
import org.hibernate.sql.model.ast.TableUpdate;
/** /**
* Base support for TableUpdateBuilder implementations
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class AbstractTableUpdateBuilder<O extends MutationOperation> public abstract class AbstractTableUpdateBuilder<O extends MutationOperation>
@ -30,27 +33,44 @@ public abstract class AbstractTableUpdateBuilder<O extends MutationOperation>
private List<ColumnValueBinding> lobValueBindings; private List<ColumnValueBinding> lobValueBindings;
public AbstractTableUpdateBuilder( public AbstractTableUpdateBuilder(
MutationTarget mutationTarget, MutationTarget<?> mutationTarget,
TableMapping tableMapping, TableMapping tableMapping,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
super( MutationType.UPDATE, mutationTarget, tableMapping, sessionFactory ); super( MutationType.UPDATE, mutationTarget, tableMapping, sessionFactory );
} }
public AbstractTableUpdateBuilder( public AbstractTableUpdateBuilder(
MutationTarget mutationTarget, MutationTarget<?> mutationTarget,
MutatingTableReference tableReference, MutatingTableReference tableReference,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
super( MutationType.UPDATE, mutationTarget, tableReference, sessionFactory ); super( MutationType.UPDATE, mutationTarget, tableReference, sessionFactory );
} }
/**
* The bindings for each key restriction (WHERE clause).
*
* @see TableUpdate#getKeyBindings
*/
protected List<ColumnValueBinding> getKeyBindings() { protected List<ColumnValueBinding> getKeyBindings() {
return keyBindings; return keyBindings;
} }
/**
* The (non-LOB) bindings for each column being updated (SET clause)
*
* @see TableUpdate#getValueBindings
*/
protected List<ColumnValueBinding> getValueBindings() { protected List<ColumnValueBinding> getValueBindings() {
return valueBindings; return valueBindings;
} }
/**
* @apiNote The distinction with {@link #getValueBindings} is to help
* in cases e.g. where a dialect needs to order all LOB bindings after
* all non-LOB bindings
*
* @see TableUpdate#getValueBindings
*/
protected List<ColumnValueBinding> getLobValueBindings() { protected List<ColumnValueBinding> getLobValueBindings() {
return lobValueBindings; return lobValueBindings;
} }

View File

@ -6,11 +6,15 @@
*/ */
package org.hibernate.sql.model.ast.builder; package org.hibernate.sql.model.ast.builder;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.model.MutationTarget; import org.hibernate.sql.model.MutationTarget;
import org.hibernate.sql.model.MutationType; import org.hibernate.sql.model.MutationType;
import org.hibernate.sql.model.TableMapping; import org.hibernate.sql.model.TableMapping;
import org.hibernate.sql.model.ast.ColumnValueParameter;
import org.hibernate.sql.model.ast.MutatingTableReference; import org.hibernate.sql.model.ast.MutatingTableReference;
import org.hibernate.sql.model.ast.TableDelete; import org.hibernate.sql.model.ast.TableDelete;
import org.hibernate.sql.model.internal.TableDeleteCustomSql; import org.hibernate.sql.model.internal.TableDeleteCustomSql;
@ -28,15 +32,17 @@ public class TableDeleteBuilderStandard
implements TableDeleteBuilder { implements TableDeleteBuilder {
private final boolean isCustomSql; private final boolean isCustomSql;
private final List<ColumnValueParameter> parameters = new ArrayList<>();
public TableDeleteBuilderStandard( public TableDeleteBuilderStandard(
MutationTarget mutationTarget, MutationTarget<?> mutationTarget,
TableMapping table, TableMapping table,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
this( mutationTarget, new MutatingTableReference( table ), sessionFactory ); this( mutationTarget, new MutatingTableReference( table ), sessionFactory );
} }
public TableDeleteBuilderStandard( public TableDeleteBuilderStandard(
MutationTarget mutationTarget, MutationTarget<?> mutationTarget,
MutatingTableReference tableReference, MutatingTableReference tableReference,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
super( MutationType.DELETE, mutationTarget, tableReference, sessionFactory ); super( MutationType.DELETE, mutationTarget, tableReference, sessionFactory );
@ -84,4 +90,13 @@ public class TableDeleteBuilderStandard
getParameters() getParameters()
); );
} }
protected List<ColumnValueParameter> getParameters() {
return parameters;
}
@Override
protected void handleParameterCreation(ColumnValueParameter parameter) {
parameters.add( parameter );
}
} }

View File

@ -13,6 +13,7 @@ import org.hibernate.sql.model.MutationOperation;
import org.hibernate.sql.model.MutationTarget; import org.hibernate.sql.model.MutationTarget;
import org.hibernate.sql.model.TableMapping; import org.hibernate.sql.model.TableMapping;
import org.hibernate.sql.model.ast.ColumnValueBinding; import org.hibernate.sql.model.ast.ColumnValueBinding;
import org.hibernate.sql.model.ast.ColumnValueParameter;
import org.hibernate.sql.model.ast.MutatingTableReference; import org.hibernate.sql.model.ast.MutatingTableReference;
import org.hibernate.sql.model.ast.RestrictedTableMutation; import org.hibernate.sql.model.ast.RestrictedTableMutation;
import org.hibernate.sql.model.internal.TableUpdateCustomSql; import org.hibernate.sql.model.internal.TableUpdateCustomSql;
@ -21,18 +22,20 @@ import org.hibernate.sql.model.internal.TableUpdateStandard;
import org.hibernate.sql.model.internal.TableUpsert; import org.hibernate.sql.model.internal.TableUpsert;
/** /**
* Standard TableUpdateBuilder implementation
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class TableUpdateBuilderStandard<O extends MutationOperation> extends AbstractTableUpdateBuilder<O> { public class TableUpdateBuilderStandard<O extends MutationOperation> extends AbstractTableUpdateBuilder<O> {
public TableUpdateBuilderStandard( public TableUpdateBuilderStandard(
MutationTarget mutationTarget, MutationTarget<?> mutationTarget,
TableMapping tableMapping, TableMapping tableMapping,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
super( mutationTarget, tableMapping, sessionFactory ); super( mutationTarget, tableMapping, sessionFactory );
} }
public TableUpdateBuilderStandard( public TableUpdateBuilderStandard(
MutationTarget mutationTarget, MutationTarget<?> mutationTarget,
MutatingTableReference tableReference, MutatingTableReference tableReference,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
super( mutationTarget, tableReference, sessionFactory ); super( mutationTarget, tableReference, sessionFactory );
@ -50,7 +53,6 @@ public class TableUpdateBuilderStandard<O extends MutationOperation> extends Abs
return (RestrictedTableMutation<O>) new TableUpdateCustomSql( return (RestrictedTableMutation<O>) new TableUpdateCustomSql(
getMutatingTable(), getMutatingTable(),
getMutationTarget(), getMutationTarget(),
getParameters(),
valueBindings, valueBindings,
getKeyRestrictionBindings(), getKeyRestrictionBindings(),
getOptimisticLockBindings() getOptimisticLockBindings()
@ -63,18 +65,22 @@ public class TableUpdateBuilderStandard<O extends MutationOperation> extends Abs
getMutationTarget(), getMutationTarget(),
valueBindings, valueBindings,
getKeyRestrictionBindings(), getKeyRestrictionBindings(),
getOptimisticLockBindings(), getOptimisticLockBindings()
getParameters()
); );
} }
return (RestrictedTableMutation<O>) new TableUpdateStandard( return (RestrictedTableMutation<O>) new TableUpdateStandard(
getMutatingTable(), getMutatingTable(),
getMutationTarget(), getMutationTarget(),
getParameters(),
valueBindings, valueBindings,
getKeyRestrictionBindings(), getKeyRestrictionBindings(),
getOptimisticLockBindings() getOptimisticLockBindings()
); );
} }
@Override
protected void handleParameterCreation(ColumnValueParameter parameter) {
// nothing to do for updates... each TableUpdate impl collects
// the parameters from the bindings in a specific order
}
} }

View File

@ -30,11 +30,20 @@ public class TableUpdateCustomSql
public TableUpdateCustomSql( public TableUpdateCustomSql(
MutatingTableReference mutatingTable, MutatingTableReference mutatingTable,
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
List<ColumnValueParameter> parameters,
List<ColumnValueBinding> valueBindings, List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings, List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings) { List<ColumnValueBinding> optLockRestrictionBindings) {
super( mutatingTable, mutationTarget, parameters, valueBindings, keyRestrictionBindings, optLockRestrictionBindings ); super( mutatingTable, mutationTarget, valueBindings, keyRestrictionBindings, optLockRestrictionBindings );
}
public TableUpdateCustomSql(
MutatingTableReference mutatingTable,
MutationTarget<?> mutationTarget,
List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings,
List<ColumnValueParameter> parameters) {
super( mutatingTable, mutationTarget, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, parameters );
} }
@Override @Override

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.model.internal;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.SqlAstWalker;
@ -18,6 +19,7 @@ import org.hibernate.sql.model.MutationTarget;
import org.hibernate.sql.model.TableMapping; import org.hibernate.sql.model.TableMapping;
import org.hibernate.sql.model.ast.AbstractRestrictedTableMutation; import org.hibernate.sql.model.ast.AbstractRestrictedTableMutation;
import org.hibernate.sql.model.ast.ColumnValueBinding; import org.hibernate.sql.model.ast.ColumnValueBinding;
import org.hibernate.sql.model.ast.ColumnValueParameter;
import org.hibernate.sql.model.ast.MutatingTableReference; import org.hibernate.sql.model.ast.MutatingTableReference;
import org.hibernate.sql.model.ast.TableUpdate; import org.hibernate.sql.model.ast.TableUpdate;
import org.hibernate.sql.model.jdbc.JdbcMutationOperation; import org.hibernate.sql.model.jdbc.JdbcMutationOperation;
@ -84,4 +86,8 @@ public class TableUpdateNoSet
@Override @Override
public void forEachValueBinding(BiConsumer<Integer, ColumnValueBinding> consumer) { public void forEachValueBinding(BiConsumer<Integer, ColumnValueBinding> consumer) {
} }
@Override
public void forEachParameter(Consumer<ColumnValueParameter> consumer) {
}
} }

View File

@ -25,22 +25,32 @@ public class TableUpdateStandard extends AbstractTableUpdate<JdbcMutationOperati
public TableUpdateStandard( public TableUpdateStandard(
MutatingTableReference mutatingTable, MutatingTableReference mutatingTable,
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
List<ColumnValueParameter> parameters,
List<ColumnValueBinding> valueBindings, List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings, List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings) { List<ColumnValueBinding> optLockRestrictionBindings) {
this( mutatingTable, mutationTarget, parameters, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, null ); super( mutatingTable, mutationTarget, valueBindings, keyRestrictionBindings, optLockRestrictionBindings );
this.whereFragment = null;
} }
public TableUpdateStandard( public TableUpdateStandard(
MutatingTableReference mutatingTable, MutatingTableReference tableReference,
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
List<ColumnValueParameter> parameters,
List<ColumnValueBinding> valueBindings, List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings, List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings, List<ColumnValueBinding> optLockRestrictionBindings,
List<ColumnValueParameter> parameters) {
this( tableReference, mutationTarget, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, parameters, null );
}
public TableUpdateStandard(
MutatingTableReference tableReference,
MutationTarget<?> mutationTarget,
List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings,
List<ColumnValueParameter> parameters,
String whereFragment) { String whereFragment) {
super( mutatingTable, mutationTarget, parameters, valueBindings, keyRestrictionBindings, optLockRestrictionBindings ); super( tableReference, mutationTarget, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, parameters );
this.whereFragment = whereFragment; this.whereFragment = whereFragment;
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.sql.model.internal;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
@ -25,6 +26,8 @@ import org.hibernate.sql.model.ast.MutatingTableReference;
import org.hibernate.sql.model.ast.RestrictedTableMutation; import org.hibernate.sql.model.ast.RestrictedTableMutation;
import org.hibernate.sql.model.ast.TableUpdate; import org.hibernate.sql.model.ast.TableUpdate;
import static org.hibernate.sql.model.ast.AbstractTableUpdate.collectParameters;
/** /**
* @apiNote Implements {@link TableUpdate} because it is fundamentally an update * @apiNote Implements {@link TableUpdate} because it is fundamentally an update
* *
@ -40,16 +43,14 @@ public class TableUpsert
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
List<ColumnValueBinding> valueBindings, List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings, List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings, List<ColumnValueBinding> optLockRestrictionBindings) {
List<ColumnValueParameter> parameters) {
this( this(
mutatingTable, mutatingTable,
mutationTarget, mutationTarget,
"upsert for " + mutationTarget.getRolePath(), "upsert for " + mutationTarget.getRolePath(),
valueBindings, valueBindings,
keyRestrictionBindings, keyRestrictionBindings,
optLockRestrictionBindings, optLockRestrictionBindings
parameters
); );
} }
@ -59,9 +60,15 @@ public class TableUpsert
String comment, String comment,
List<ColumnValueBinding> valueBindings, List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings, List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings, List<ColumnValueBinding> optLockRestrictionBindings) {
List<ColumnValueParameter> parameters) { super(
super( mutatingTable, mutationTarget, comment, keyRestrictionBindings, optLockRestrictionBindings, parameters ); mutatingTable,
mutationTarget,
comment,
keyRestrictionBindings,
optLockRestrictionBindings,
collectParameters( valueBindings, keyRestrictionBindings, optLockRestrictionBindings )
);
this.valueBindings = valueBindings; this.valueBindings = valueBindings;
} }
@ -90,6 +97,20 @@ public class TableUpsert
return getMutatingTable().getTableMapping().getUpdateDetails().getExpectation(); return getMutatingTable().getTableMapping().getUpdateDetails().getExpectation();
} }
@Override
public void forEachParameter(Consumer<ColumnValueParameter> consumer) {
final BiConsumer<Integer,ColumnValueBinding> intermediateConsumer = (index, binding) -> {
final ColumnValueParameter parameter = binding.getValueExpression().getParameter();
if ( parameter != null ) {
consumer.accept( parameter );
}
};
forEachThing( getValueBindings(), intermediateConsumer );
forEachThing( getKeyBindings(), intermediateConsumer );
forEachThing( getOptimisticLockBindings(), intermediateConsumer );
}
public List<ColumnValueBinding> getValueBindings() { public List<ColumnValueBinding> getValueBindings() {
return valueBindings; return valueBindings;
} }

View File

@ -140,8 +140,9 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
} }
} }
else { else {
// there are some non-null values for the table - we need to update or insert the values // there are some non-null values for the table - we need to update or insert the values.
// first, try the update and see if any row was affected
final boolean wasUpdated; final boolean wasUpdated;
if ( valuesAnalysis.getTablesWithPreviousNonNullValues().contains( tableMapping ) ) { if ( valuesAnalysis.getTablesWithPreviousNonNullValues().contains( tableMapping ) ) {
// either // either
@ -302,10 +303,7 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
private boolean performUpdate( private boolean performUpdate(
JdbcValueBindings jdbcValueBindings, JdbcValueBindings jdbcValueBindings,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
MODEL_MUTATION_LOGGER.tracef( MODEL_MUTATION_LOGGER.tracef( "#performUpdate(%s)", tableMapping.getTableName() );
"#performUpdate(%s)",
tableMapping.getTableName()
);
final TableUpdate<JdbcMutationOperation> tableUpdate; final TableUpdate<JdbcMutationOperation> tableUpdate;
if ( tableMapping.getUpdateDetails() != null if ( tableMapping.getUpdateDetails() != null
@ -313,20 +311,20 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
tableUpdate = new TableUpdateCustomSql( tableUpdate = new TableUpdateCustomSql(
new MutatingTableReference( tableMapping ), new MutatingTableReference( tableMapping ),
mutationTarget, mutationTarget,
parameters,
valueBindings, valueBindings,
keyBindings, keyBindings,
optimisticLockBindings optimisticLockBindings,
parameters
); );
} }
else { else {
tableUpdate = new TableUpdateStandard( tableUpdate = new TableUpdateStandard(
new MutatingTableReference( tableMapping ), new MutatingTableReference( tableMapping ),
mutationTarget, mutationTarget,
parameters,
valueBindings, valueBindings,
keyBindings, keyBindings,
optimisticLockBindings optimisticLockBindings,
parameters
); );
} }

View File

@ -6,7 +6,6 @@ import org.hibernate.annotations.SQLInsert;
import org.hibernate.annotations.SQLUpdate; import org.hibernate.annotations.SQLUpdate;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -19,6 +18,7 @@ import jakarta.persistence.SecondaryTable;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import jakarta.persistence.Version; import jakarta.persistence.Version;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.annotations.GenerationTime.ALWAYS; import static org.hibernate.annotations.GenerationTime.ALWAYS;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -26,7 +26,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
@DomainModel(annotatedClasses = CustomSqlGeneratedTest.Custom.class) @DomainModel(annotatedClasses = CustomSqlGeneratedTest.Custom.class)
public class CustomSqlGeneratedTest { public class CustomSqlGeneratedTest {
@Test @Test
@FailureExpected( reason = "Change in expected order of columns in UPDATE SET clause causes problems with `@SQLUpdate`" )
public void testCustomSqlWithGenerated(SessionFactoryScope scope) { public void testCustomSqlWithGenerated(SessionFactoryScope scope) {
Custom c = new Custom(); Custom c = new Custom();
c.name = "name"; c.name = "name";
@ -41,8 +40,8 @@ public class CustomSqlGeneratedTest {
cc.text = "more text"; cc.text = "more text";
s.flush(); s.flush();
cc = s.find(Custom.class, c.id); cc = s.find(Custom.class, c.id);
assertEquals(cc.text, "MORE TEXT"); assertThat(cc.text ).isEqualTo( "MORE TEXT");
assertEquals(cc.name, "EMAN"); assertThat( cc.name ).isEqualTo( "EMAN" );
s.remove(cc); s.remove(cc);
s.flush(); s.flush();
cc = s.find(Custom.class, c.id); cc = s.find(Custom.class, c.id);

View File

@ -5,7 +5,6 @@ import org.hibernate.annotations.SQLInsert;
import org.hibernate.annotations.SQLUpdate; import org.hibernate.annotations.SQLUpdate;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -24,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
@DomainModel(annotatedClasses = CustomSqlTest.Custom.class) @DomainModel(annotatedClasses = CustomSqlTest.Custom.class)
public class CustomSqlTest { public class CustomSqlTest {
@Test @Test
@FailureExpected( reason = "Change in expected order of columns in UPDATE SET clause causes problems with `@SQLUpdate`" )
public void testCustomSql(SessionFactoryScope scope) { public void testCustomSql(SessionFactoryScope scope) {
Custom c = new Custom(); Custom c = new Custom();
c.name = "name"; c.name = "name";