HHH-15393 - Improve write-paths to use mapping model
This commit is contained in:
parent
c04caa18de
commit
1c083a5863
|
@ -38,7 +38,6 @@ public class TableInsertReturningBuilder extends AbstractTableInsertBuilder {
|
|||
getMutatingTable(),
|
||||
getMutationTarget(),
|
||||
combine( getValueBindingList(), getKeyBindingList(), getLobValueBindingList() ),
|
||||
true,
|
||||
Collections.singletonList( new ColumnReference( getMutatingTable(), identifierMapping ) ),
|
||||
getParameters()
|
||||
);
|
||||
|
|
|
@ -1785,6 +1785,7 @@ public abstract class AbstractCollectionPersister
|
|||
return (RestrictedTableMutation) new TableDeleteStandard(
|
||||
tableReference,
|
||||
this,
|
||||
"one-shot delete for " + getRolePath(),
|
||||
keyRestrictionBindings,
|
||||
Collections.emptyList(),
|
||||
parameters
|
||||
|
|
|
@ -389,6 +389,7 @@ public class OneToManyPersister extends AbstractCollectionPersister {
|
|||
return new TableUpdateStandard(
|
||||
tableReference,
|
||||
this,
|
||||
"one-shot delete for " + getRolePath(),
|
||||
valueBindings,
|
||||
keyRestrictionBindings,
|
||||
null,
|
||||
|
|
|
@ -256,10 +256,10 @@ import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
|
|||
import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
|
||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
import org.hibernate.tuple.ValueGenerationStrategy;
|
||||
import org.hibernate.tuple.InDatabaseValueGenerationStrategy;
|
||||
import org.hibernate.tuple.GenerationTiming;
|
||||
import org.hibernate.tuple.InDatabaseValueGenerationStrategy;
|
||||
import org.hibernate.tuple.NonIdentifierAttribute;
|
||||
import org.hibernate.tuple.ValueGenerationStrategy;
|
||||
import org.hibernate.tuple.entity.EntityBasedAssociationAttribute;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
import org.hibernate.type.AnyType;
|
||||
|
@ -1934,6 +1934,10 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
@Override
|
||||
public Object forceVersionIncrement(Object id, Object currentVersion, SharedSessionContractImplementor session) {
|
||||
if ( superMappingType != null ) {
|
||||
return superMappingType.getEntityPersister().forceVersionIncrement( id, currentVersion, session );
|
||||
}
|
||||
|
||||
if ( !isVersioned() ) {
|
||||
throw new AssertionFailure( "cannot force version increment on non-versioned entity" );
|
||||
}
|
||||
|
@ -1944,6 +1948,7 @@ public abstract class AbstractEntityPersister
|
|||
throw new HibernateException( "LockMode.FORCE is currently not supported for generated version properties" );
|
||||
|
||||
}
|
||||
|
||||
final EntityVersionMapping versionMapping = getVersionMapping();
|
||||
final Object nextVersion = getVersionJavaType().next(
|
||||
currentVersion,
|
||||
|
@ -1960,36 +1965,38 @@ public abstract class AbstractEntityPersister
|
|||
);
|
||||
}
|
||||
|
||||
// todo : cache this sql...
|
||||
String versionIncrementString = generateVersionIncrementUpdateString();
|
||||
PreparedStatement st;
|
||||
try {
|
||||
st = session
|
||||
.getJdbcCoordinator()
|
||||
.getStatementPreparer()
|
||||
.prepareStatement( versionIncrementString, false );
|
||||
try {
|
||||
getVersionType().nullSafeSet( st, nextVersion, 1, session );
|
||||
getIdentifierType().nullSafeSet( st, id, 2, session );
|
||||
getVersionType().nullSafeSet( st, currentVersion, 2 + getIdentifierColumnSpan(), session );
|
||||
int rows = session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
|
||||
if ( rows != 1 ) {
|
||||
throw new StaleObjectStateException( getEntityName(), id );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( st );
|
||||
session.getJdbcCoordinator().afterStatementExecution();
|
||||
}
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
throw session.getJdbcServices().getSqlExceptionHelper().convert(
|
||||
sqle,
|
||||
"could not retrieve version: " +
|
||||
MessageHelper.infoString( this, id, getFactory() ),
|
||||
getVersionSelectString()
|
||||
);
|
||||
}
|
||||
updateCoordinator.forceVersionIncrement( id, currentVersion, nextVersion, session );
|
||||
|
||||
// // todo : cache this sql...
|
||||
// String versionIncrementString = generateVersionIncrementUpdateString();
|
||||
// PreparedStatement st;
|
||||
// try {
|
||||
// st = session
|
||||
// .getJdbcCoordinator()
|
||||
// .getStatementPreparer()
|
||||
// .prepareStatement( versionIncrementString, false );
|
||||
// try {
|
||||
// getVersionType().nullSafeSet( st, nextVersion, 1, session );
|
||||
// getIdentifierType().nullSafeSet( st, id, 2, session );
|
||||
// getVersionType().nullSafeSet( st, currentVersion, 2 + getIdentifierColumnSpan(), session );
|
||||
// int rows = session.getJdbcCoordinator().getResultSetReturn().executeUpdate( st );
|
||||
// if ( rows != 1 ) {
|
||||
// throw new StaleObjectStateException( getEntityName(), id );
|
||||
// }
|
||||
// }
|
||||
// finally {
|
||||
// session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( st );
|
||||
// session.getJdbcCoordinator().afterStatementExecution();
|
||||
// }
|
||||
// }
|
||||
// catch (SQLException sqle) {
|
||||
// throw session.getJdbcServices().getSqlExceptionHelper().convert(
|
||||
// sqle,
|
||||
// "could not retrieve version: " +
|
||||
// MessageHelper.infoString( this, id, getFactory() ),
|
||||
// getVersionSelectString()
|
||||
// );
|
||||
// }
|
||||
|
||||
return nextVersion;
|
||||
}
|
||||
|
|
|
@ -31,4 +31,10 @@ public interface UpdateCoordinator {
|
|||
int[] dirtyAttributeIndexes,
|
||||
boolean hasDirtyCollection,
|
||||
SharedSessionContractImplementor session);
|
||||
|
||||
void forceVersionIncrement(
|
||||
Object id,
|
||||
Object currentVersion,
|
||||
Object nextVersion,
|
||||
SharedSessionContractImplementor session);
|
||||
}
|
||||
|
|
|
@ -31,4 +31,9 @@ public class UpdateCoordinatorNoOp implements UpdateCoordinator {
|
|||
public void coordinateUpdate(Object entity, Object id, Object rowId, Object[] values, Object oldVersion, Object[] incomingOldValues, int[] dirtyAttributeIndexes, boolean hasDirtyCollection, SharedSessionContractImplementor session) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceVersionIncrement(Object id, Object currentVersion, Object nextVersion, SharedSessionContractImplementor session) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
|
@ -49,9 +50,9 @@ import org.hibernate.sql.model.ast.builder.TableUpdateBuilderSkipped;
|
|||
import org.hibernate.sql.model.ast.builder.TableUpdateBuilderStandard;
|
||||
import org.hibernate.sql.model.internal.MutationOperationGroupSingle;
|
||||
import org.hibernate.sql.model.jdbc.JdbcMutationOperation;
|
||||
import org.hibernate.tuple.ValueGenerationStrategy;
|
||||
import org.hibernate.tuple.InDatabaseValueGenerationStrategy;
|
||||
import org.hibernate.tuple.InMemoryValueGenerationStrategy;
|
||||
import org.hibernate.tuple.ValueGenerationStrategy;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
|
||||
import static org.hibernate.engine.OptimisticLockStyle.ALL;
|
||||
|
@ -102,6 +103,18 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
return ( entry == null ? entityPersister().isMutable() : entry.isModifiableEntity() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceVersionIncrement(
|
||||
Object id,
|
||||
Object currentVersion,
|
||||
Object nextVersion,
|
||||
SharedSessionContractImplementor session) {
|
||||
if ( versionUpdateGroup == null ) {
|
||||
throw new HibernateException( "Cannot force version increment relative to sub-type; use the root type" );
|
||||
}
|
||||
doVersionUpdate( null, id, nextVersion, currentVersion, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void coordinateUpdate(
|
||||
Object entity,
|
||||
|
@ -606,6 +619,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
);
|
||||
|
||||
try {
|
||||
//noinspection SuspiciousMethodCalls
|
||||
mutationExecutor.execute(
|
||||
entity,
|
||||
valuesAnalysis,
|
||||
|
@ -799,6 +813,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
entity,
|
||||
valuesAnalysis,
|
||||
(tableMapping) -> {
|
||||
//noinspection SuspiciousMethodCalls
|
||||
if ( tableMapping.isOptional()
|
||||
&& !valuesAnalysis.tablesWithNonNullValues.contains( tableMapping ) ) {
|
||||
// the table is optional, and we have null values for all of its columns
|
||||
|
@ -806,7 +821,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
return false;
|
||||
}
|
||||
|
||||
//noinspection RedundantIfStatement
|
||||
//noinspection SuspiciousMethodCalls,RedundantIfStatement
|
||||
if ( !valuesAnalysis.tablesNeedingUpdate.contains( tableMapping ) ) {
|
||||
// nothing changed
|
||||
return false;
|
||||
|
@ -842,6 +857,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
final RestrictedTableMutationBuilder<?,?> tableUpdateBuilder;
|
||||
|
||||
final MutatingTableReference tableReference = new MutatingTableReference( tableMapping );
|
||||
//noinspection SuspiciousMethodCalls
|
||||
if ( ! valuesAnalysis.tablesNeedingUpdate.contains( tableReference.getTableMapping() ) ) {
|
||||
// this table does not need updating
|
||||
tableUpdateBuilder = new TableUpdateBuilderSkipped( tableReference );
|
||||
|
@ -1371,26 +1387,6 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
null,
|
||||
valuesAnalysis,
|
||||
(position, attribute) -> valuesAnalysis.getAttributeAnalyses().get( position ).isDirty(),
|
||||
// // optimistic locking (restriction) checker
|
||||
// (position, attribute) -> {
|
||||
// final OptimisticLockStyle optimisticLockStyle = entityPersister()
|
||||
// .getEntityMetamodel()
|
||||
// .getOptimisticLockStyle();
|
||||
//
|
||||
// if ( optimisticLockStyle == ALL ) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// if ( optimisticLockStyle == VERSION ) {
|
||||
// final EntityVersionMapping versionMapping = entityPersister().getVersionMapping();
|
||||
// if ( versionMapping == null ) {
|
||||
// return false;
|
||||
// }
|
||||
// return attribute == versionMapping.getVersionAttribute();
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// },
|
||||
// session
|
||||
null
|
||||
);
|
||||
|
@ -1406,12 +1402,18 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
return null;
|
||||
}
|
||||
|
||||
if ( entityPersister().getSuperMappingType() != null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final TableUpdateBuilderStandard updateBuilder = new TableUpdateBuilderStandard(
|
||||
entityPersister(),
|
||||
entityPersister().getIdentifierTableMapping(),
|
||||
factory()
|
||||
);
|
||||
|
||||
updateBuilder.setSqlComment( "forced version increment for " + entityPersister().getRolePath() );
|
||||
|
||||
updateBuilder.addValueColumn( versionMapping );
|
||||
|
||||
entityPersister().getIdentifierMapping().forEachSelectable( (selectionIndex, selectableMapping) -> {
|
||||
|
@ -1439,10 +1441,6 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
|
|||
@FunctionalInterface
|
||||
private interface InclusionChecker {
|
||||
boolean include(int position, SingularAttributeMapping attribute);
|
||||
|
||||
default boolean reject(int position, SingularAttributeMapping attribute) {
|
||||
return !include( position, attribute );
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
|
|
@ -7643,6 +7643,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
}
|
||||
|
||||
private void renderInsertInto(TableInsertStandard tableInsert) {
|
||||
applySqlComment( tableInsert.getMutationComment() );
|
||||
|
||||
if ( tableInsert.getNumberOfValueBindings() == 0 ) {
|
||||
renderInsertIntoNoColumns( tableInsert );
|
||||
return;
|
||||
|
@ -7710,6 +7712,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
public void visitStandardTableUpdate(TableUpdateStandard tableUpdate) {
|
||||
getCurrentClauseStack().push( Clause.UPDATE );
|
||||
try {
|
||||
applySqlComment( tableUpdate.getMutationComment() );
|
||||
|
||||
sqlBuffer.append( "update " );
|
||||
appendSql( tableUpdate.getMutatingTable().getTableName() );
|
||||
registerAffectedTable( tableUpdate.getMutatingTable().getTableName() );
|
||||
|
@ -7775,6 +7779,16 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
}
|
||||
}
|
||||
|
||||
private void applySqlComment(String comment) {
|
||||
if ( sessionFactory.getSessionFactoryOptions().isCommentsEnabled() ) {
|
||||
if ( comment != null ) {
|
||||
appendSql( "/* " );
|
||||
appendSql( Dialect.escapeComment( comment ) );
|
||||
appendSql( " */" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCustomTableUpdate(TableUpdateCustomSql tableUpdate) {
|
||||
assert sqlBuffer.toString().isEmpty();
|
||||
|
@ -7787,6 +7801,8 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
public void visitStandardTableDelete(TableDeleteStandard tableDelete) {
|
||||
getCurrentClauseStack().push( Clause.DELETE );
|
||||
try {
|
||||
applySqlComment( tableDelete.getMutationComment() );
|
||||
|
||||
sqlBuffer.append( "delete from " );
|
||||
appendSql( tableDelete.getMutatingTable().getTableName() );
|
||||
registerAffectedTable( tableDelete.getMutatingTable().getTableName() );
|
||||
|
|
|
@ -31,13 +31,14 @@ public abstract class AbstractTableUpdate<O extends MutationOperation>
|
|||
public AbstractTableUpdate(
|
||||
MutatingTableReference mutatingTable,
|
||||
MutationTarget<?> mutationTarget,
|
||||
String sqlComment,
|
||||
List<ColumnValueBinding> valueBindings,
|
||||
List<ColumnValueBinding> keyRestrictionBindings,
|
||||
List<ColumnValueBinding> optLockRestrictionBindings) {
|
||||
super(
|
||||
mutatingTable,
|
||||
mutationTarget,
|
||||
"update for " + mutationTarget.getNavigableRole(),
|
||||
sqlComment,
|
||||
keyRestrictionBindings,
|
||||
optLockRestrictionBindings,
|
||||
collectParameters( valueBindings, keyRestrictionBindings, optLockRestrictionBindings )
|
||||
|
@ -49,6 +50,7 @@ public abstract class AbstractTableUpdate<O extends MutationOperation>
|
|||
public <T> AbstractTableUpdate(
|
||||
MutatingTableReference tableReference,
|
||||
MutationTarget<?> mutationTarget,
|
||||
String sqlComment,
|
||||
List<ColumnValueBinding> valueBindings,
|
||||
List<ColumnValueBinding> keyRestrictionBindings,
|
||||
List<ColumnValueBinding> optLockRestrictionBindings,
|
||||
|
@ -56,7 +58,7 @@ public abstract class AbstractTableUpdate<O extends MutationOperation>
|
|||
super(
|
||||
tableReference,
|
||||
mutationTarget,
|
||||
"update for " + mutationTarget.getNavigableRole(),
|
||||
sqlComment,
|
||||
keyRestrictionBindings,
|
||||
optLockRestrictionBindings,
|
||||
parameters
|
||||
|
|
|
@ -33,11 +33,14 @@ public abstract class AbstractTableInsertBuilder
|
|||
|
||||
private final List<ColumnValueParameter> parameters = new ArrayList<>();
|
||||
|
||||
private String sqlComment;
|
||||
|
||||
public AbstractTableInsertBuilder(
|
||||
MutationTarget<?> mutationTarget,
|
||||
TableMapping table,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
super( MutationType.INSERT, mutationTarget, table, sessionFactory );
|
||||
this.sqlComment = "insert for " + mutationTarget.getRolePath();
|
||||
}
|
||||
|
||||
public AbstractTableInsertBuilder(
|
||||
|
@ -45,6 +48,15 @@ public abstract class AbstractTableInsertBuilder
|
|||
MutatingTableReference tableReference,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
super( MutationType.INSERT, mutationTarget, tableReference, sessionFactory );
|
||||
this.sqlComment = "insert for " + mutationTarget.getRolePath();
|
||||
}
|
||||
|
||||
public String getSqlComment() {
|
||||
return sqlComment;
|
||||
}
|
||||
|
||||
public void setSqlComment(String sqlComment) {
|
||||
this.sqlComment = sqlComment;
|
||||
}
|
||||
|
||||
protected List<ColumnValueBinding> getKeyBindingList() {
|
||||
|
|
|
@ -32,11 +32,14 @@ public abstract class AbstractTableUpdateBuilder<O extends MutationOperation>
|
|||
private final List<ColumnValueBinding> valueBindings = new ArrayList<>();
|
||||
private List<ColumnValueBinding> lobValueBindings;
|
||||
|
||||
private String sqlComment;
|
||||
|
||||
public AbstractTableUpdateBuilder(
|
||||
MutationTarget<?> mutationTarget,
|
||||
TableMapping tableMapping,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
super( MutationType.UPDATE, mutationTarget, tableMapping, sessionFactory );
|
||||
this.sqlComment = "update for " + mutationTarget.getRolePath();
|
||||
}
|
||||
|
||||
public AbstractTableUpdateBuilder(
|
||||
|
@ -46,6 +49,14 @@ public abstract class AbstractTableUpdateBuilder<O extends MutationOperation>
|
|||
super( MutationType.UPDATE, mutationTarget, tableReference, sessionFactory );
|
||||
}
|
||||
|
||||
public String getSqlComment() {
|
||||
return sqlComment;
|
||||
}
|
||||
|
||||
public void setSqlComment(String sqlComment) {
|
||||
this.sqlComment = sqlComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* The bindings for each key restriction (WHERE clause).
|
||||
*
|
||||
|
|
|
@ -34,6 +34,8 @@ public class TableDeleteBuilderStandard
|
|||
|
||||
private final List<ColumnValueParameter> parameters = new ArrayList<>();
|
||||
|
||||
private String sqlComment;
|
||||
|
||||
public TableDeleteBuilderStandard(
|
||||
MutationTarget<?> mutationTarget,
|
||||
TableMapping table,
|
||||
|
@ -48,6 +50,15 @@ public class TableDeleteBuilderStandard
|
|||
super( MutationType.DELETE, mutationTarget, tableReference, sessionFactory );
|
||||
|
||||
this.isCustomSql = tableReference.getTableMapping().getDeleteDetails().getCustomSql() != null;
|
||||
this.sqlComment = "delete for " + mutationTarget.getRolePath();
|
||||
}
|
||||
|
||||
public String getSqlComment() {
|
||||
return sqlComment;
|
||||
}
|
||||
|
||||
public void setSqlComment(String sqlComment) {
|
||||
this.sqlComment = sqlComment;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,6 +87,7 @@ public class TableDeleteBuilderStandard
|
|||
return new TableDeleteCustomSql(
|
||||
getMutatingTable(),
|
||||
getMutationTarget(),
|
||||
sqlComment,
|
||||
getKeyRestrictionBindings(),
|
||||
getOptimisticLockBindings(),
|
||||
getParameters()
|
||||
|
@ -85,6 +97,7 @@ public class TableDeleteBuilderStandard
|
|||
return new TableDeleteStandard(
|
||||
getMutatingTable(),
|
||||
getMutationTarget(),
|
||||
sqlComment,
|
||||
getKeyRestrictionBindings(),
|
||||
getOptimisticLockBindings(),
|
||||
getParameters()
|
||||
|
|
|
@ -6,14 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.sql.model.ast.builder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.model.MutationTarget;
|
||||
import org.hibernate.sql.model.TableMapping;
|
||||
import org.hibernate.sql.model.ast.MutatingTableReference;
|
||||
|
@ -27,51 +22,24 @@ import org.hibernate.sql.model.internal.TableInsertStandard;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TableInsertBuilderStandard extends AbstractTableInsertBuilder {
|
||||
private final boolean returningGeneratedKeys;
|
||||
private final boolean isCustomSql;
|
||||
private List<ColumnReference> returningColumnsList;
|
||||
|
||||
public TableInsertBuilderStandard(
|
||||
MutationTarget mutationTarget,
|
||||
MutationTarget<?> mutationTarget,
|
||||
TableMapping table,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
super( mutationTarget, table, sessionFactory );
|
||||
|
||||
final Dialect dialect = getJdbcServices().getDialect();
|
||||
this.returningGeneratedKeys = dialect.getDefaultUseGetGeneratedKeys();
|
||||
|
||||
this.isCustomSql = table.getInsertDetails().getCustomSql() != null;
|
||||
}
|
||||
|
||||
public TableInsertBuilderStandard(
|
||||
MutationTarget mutationTarget,
|
||||
MutationTarget<?> mutationTarget,
|
||||
MutatingTableReference tableReference,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
super( mutationTarget, tableReference, sessionFactory );
|
||||
|
||||
final Dialect dialect = getJdbcServices().getDialect();
|
||||
this.returningGeneratedKeys = dialect.getDefaultUseGetGeneratedKeys();
|
||||
|
||||
this.isCustomSql = tableReference.getTableMapping().getInsertDetails().getCustomSql() != null;
|
||||
}
|
||||
|
||||
public boolean isReturningGeneratedKeys() {
|
||||
return returningGeneratedKeys;
|
||||
}
|
||||
|
||||
public List<ColumnReference> getReturningColumns() {
|
||||
return returningColumnsList == null ? Collections.emptyList() : returningColumnsList;
|
||||
}
|
||||
|
||||
public ColumnReference addReturningColumn(SelectableMapping selectableMapping) {
|
||||
final ColumnReference columnReference = new ColumnReference( (String) null, selectableMapping, null );
|
||||
if ( returningColumnsList == null ) {
|
||||
returningColumnsList = new ArrayList<>();
|
||||
}
|
||||
returningColumnsList.add( columnReference );
|
||||
return columnReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableInsert buildMutation() {
|
||||
if ( isCustomSql ) {
|
||||
|
@ -87,8 +55,7 @@ public class TableInsertBuilderStandard extends AbstractTableInsertBuilder {
|
|||
getMutatingTable(),
|
||||
getMutationTarget(),
|
||||
combine( getValueBindingList(), getKeyBindingList(), getLobValueBindingList() ),
|
||||
returningGeneratedKeys,
|
||||
returningColumnsList,
|
||||
Collections.emptyList(),
|
||||
getParameters()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.hibernate.sql.model.internal.TableUpsert;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TableUpdateBuilderStandard<O extends MutationOperation> extends AbstractTableUpdateBuilder<O> {
|
||||
|
||||
public TableUpdateBuilderStandard(
|
||||
MutationTarget<?> mutationTarget,
|
||||
TableMapping tableMapping,
|
||||
|
@ -53,6 +54,7 @@ public class TableUpdateBuilderStandard<O extends MutationOperation> extends Abs
|
|||
return (RestrictedTableMutation<O>) new TableUpdateCustomSql(
|
||||
getMutatingTable(),
|
||||
getMutationTarget(),
|
||||
getSqlComment(),
|
||||
valueBindings,
|
||||
getKeyRestrictionBindings(),
|
||||
getOptimisticLockBindings()
|
||||
|
@ -72,6 +74,7 @@ public class TableUpdateBuilderStandard<O extends MutationOperation> extends Abs
|
|||
return (RestrictedTableMutation<O>) new TableUpdateStandard(
|
||||
getMutatingTable(),
|
||||
getMutationTarget(),
|
||||
getSqlComment(),
|
||||
valueBindings,
|
||||
getKeyRestrictionBindings(),
|
||||
getOptimisticLockBindings()
|
||||
|
|
|
@ -28,10 +28,11 @@ public class TableDeleteCustomSql extends AbstractTableDelete implements CustomS
|
|||
public TableDeleteCustomSql(
|
||||
MutatingTableReference mutatingTable,
|
||||
MutationTarget<?> mutationTarget,
|
||||
String sqlComment,
|
||||
List<ColumnValueBinding> keyRestrictionBindings,
|
||||
List<ColumnValueBinding> optLockRestrictionBindings,
|
||||
List<ColumnValueParameter> parameters) {
|
||||
super( mutatingTable, mutationTarget, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
super( mutatingTable, mutationTarget, sqlComment, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,10 +22,11 @@ public class TableDeleteStandard extends AbstractTableDelete {
|
|||
public TableDeleteStandard(
|
||||
MutatingTableReference mutatingTable,
|
||||
MutationTarget<?> mutationTarget,
|
||||
String sqlComment,
|
||||
List<ColumnValueBinding> keyRestrictionBindings,
|
||||
List<ColumnValueBinding> optLockRestrictionBindings,
|
||||
List<ColumnValueParameter> parameters) {
|
||||
super( mutatingTable, mutationTarget, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
super( mutatingTable, mutationTarget, sqlComment, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,18 +21,15 @@ import org.hibernate.sql.model.ast.MutatingTableReference;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TableInsertStandard extends AbstractTableInsert {
|
||||
private final boolean returnGeneratedKeys;
|
||||
private final List<ColumnReference> returningColumns;
|
||||
|
||||
public TableInsertStandard(
|
||||
MutatingTableReference mutatingTable,
|
||||
MutationTarget<?> mutationTarget,
|
||||
List<ColumnValueBinding> valueBindings,
|
||||
boolean returnGeneratedKeys,
|
||||
List<ColumnReference> returningColumns,
|
||||
List<ColumnValueParameter> parameters) {
|
||||
super( mutatingTable, mutationTarget, parameters, valueBindings );
|
||||
this.returnGeneratedKeys = returnGeneratedKeys;
|
||||
this.returningColumns = returningColumns;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,20 +30,22 @@ public class TableUpdateCustomSql
|
|||
public TableUpdateCustomSql(
|
||||
MutatingTableReference mutatingTable,
|
||||
MutationTarget<?> mutationTarget,
|
||||
String sqlComment,
|
||||
List<ColumnValueBinding> valueBindings,
|
||||
List<ColumnValueBinding> keyRestrictionBindings,
|
||||
List<ColumnValueBinding> optLockRestrictionBindings) {
|
||||
super( mutatingTable, mutationTarget, valueBindings, keyRestrictionBindings, optLockRestrictionBindings );
|
||||
super( mutatingTable, mutationTarget, sqlComment, valueBindings, keyRestrictionBindings, optLockRestrictionBindings );
|
||||
}
|
||||
|
||||
public TableUpdateCustomSql(
|
||||
MutatingTableReference mutatingTable,
|
||||
MutationTarget<?> mutationTarget,
|
||||
String sqlComment,
|
||||
List<ColumnValueBinding> valueBindings,
|
||||
List<ColumnValueBinding> keyRestrictionBindings,
|
||||
List<ColumnValueBinding> optLockRestrictionBindings,
|
||||
List<ColumnValueParameter> parameters) {
|
||||
super( mutatingTable, mutationTarget, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
super( mutatingTable, mutationTarget, sqlComment, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,38 +25,41 @@ public class TableUpdateStandard extends AbstractTableUpdate<JdbcMutationOperati
|
|||
public TableUpdateStandard(
|
||||
MutatingTableReference mutatingTable,
|
||||
MutationTarget<?> mutationTarget,
|
||||
String sqlComment,
|
||||
List<ColumnValueBinding> valueBindings,
|
||||
List<ColumnValueBinding> keyRestrictionBindings,
|
||||
List<ColumnValueBinding> optLockRestrictionBindings) {
|
||||
super( mutatingTable, mutationTarget, valueBindings, keyRestrictionBindings, optLockRestrictionBindings );
|
||||
super( mutatingTable, mutationTarget, sqlComment, valueBindings, keyRestrictionBindings, optLockRestrictionBindings );
|
||||
this.whereFragment = null;
|
||||
}
|
||||
|
||||
public TableUpdateStandard(
|
||||
MutatingTableReference tableReference,
|
||||
MutationTarget<?> mutationTarget,
|
||||
String sqlComment,
|
||||
List<ColumnValueBinding> valueBindings,
|
||||
List<ColumnValueBinding> keyRestrictionBindings,
|
||||
List<ColumnValueBinding> optLockRestrictionBindings,
|
||||
List<ColumnValueParameter> parameters) {
|
||||
this( tableReference, mutationTarget, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, parameters, null );
|
||||
this( tableReference, mutationTarget, sqlComment, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, parameters, null );
|
||||
}
|
||||
|
||||
public TableUpdateStandard(
|
||||
MutatingTableReference tableReference,
|
||||
MutationTarget<?> mutationTarget,
|
||||
String sqlComment,
|
||||
List<ColumnValueBinding> valueBindings,
|
||||
List<ColumnValueBinding> keyRestrictionBindings,
|
||||
List<ColumnValueBinding> optLockRestrictionBindings,
|
||||
List<ColumnValueParameter> parameters,
|
||||
String whereFragment) {
|
||||
super( tableReference, mutationTarget, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
super( tableReference, mutationTarget, sqlComment, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
this.whereFragment = whereFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomSql() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -271,6 +271,7 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
|
|||
tableDelete = new TableDeleteCustomSql(
|
||||
new MutatingTableReference( tableMapping ),
|
||||
getMutationTarget(),
|
||||
"upsert delete for " + mutationTarget.getRolePath(),
|
||||
keyBindings,
|
||||
optimisticLockBindings,
|
||||
parameters
|
||||
|
@ -280,6 +281,7 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
|
|||
tableDelete = new TableDeleteStandard(
|
||||
new MutatingTableReference( tableMapping ),
|
||||
getMutationTarget(),
|
||||
"upsert delete for " + mutationTarget.getRolePath(),
|
||||
keyBindings,
|
||||
optimisticLockBindings,
|
||||
parameters
|
||||
|
@ -311,6 +313,7 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
|
|||
tableUpdate = new TableUpdateCustomSql(
|
||||
new MutatingTableReference( tableMapping ),
|
||||
mutationTarget,
|
||||
"upsert update for " + mutationTarget.getRolePath(),
|
||||
valueBindings,
|
||||
keyBindings,
|
||||
optimisticLockBindings,
|
||||
|
@ -321,6 +324,7 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
|
|||
tableUpdate = new TableUpdateStandard(
|
||||
new MutatingTableReference( tableMapping ),
|
||||
mutationTarget,
|
||||
"upsert update for " + mutationTarget.getRolePath(),
|
||||
valueBindings,
|
||||
keyBindings,
|
||||
optimisticLockBindings,
|
||||
|
@ -427,7 +431,6 @@ public class OptionalTableUpdateOperation implements SelfExecutingUpdateOperatio
|
|||
new MutatingTableReference( tableMapping ),
|
||||
getMutationTarget(),
|
||||
CollectionHelper.combine( valueBindings, keyBindings ),
|
||||
false,
|
||||
Collections.emptyList(),
|
||||
parameters
|
||||
);
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||
*/
|
||||
package org.hibernate.orm.test.sql;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
||||
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Setting;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Version;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@ServiceRegistry(
|
||||
settings = @Setting( name = AvailableSettings.USE_SQL_COMMENTS, value = "true" )
|
||||
)
|
||||
@DomainModel( annotatedClasses = StatementCommentTests.VersionedEntity.class )
|
||||
@SessionFactory( useCollectingStatementInspector = true )
|
||||
public class StatementCommentTests {
|
||||
@Test
|
||||
public void testEntityMutationComments(SessionFactoryScope scope) {
|
||||
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
|
||||
inspector.clear();
|
||||
|
||||
// insert
|
||||
scope.inTransaction( (session) -> {
|
||||
session.persist( new VersionedEntity( 1, "tbd" ) );
|
||||
} );
|
||||
checkEntityComments( inspector );
|
||||
|
||||
// update
|
||||
scope.inTransaction( (session) -> {
|
||||
final VersionedEntity entity = session.find( VersionedEntity.class, 1 );
|
||||
inspector.clear();
|
||||
entity.setName( "The One" );
|
||||
} );
|
||||
checkEntityComments( inspector );
|
||||
|
||||
// forced version increment
|
||||
scope.inTransaction( (session) -> {
|
||||
final VersionedEntity entity = session.find( VersionedEntity.class, 1 );
|
||||
inspector.clear();
|
||||
session.lock( entity, LockMode.OPTIMISTIC_FORCE_INCREMENT );
|
||||
} );
|
||||
checkEntityComments( inspector );
|
||||
|
||||
// delete
|
||||
scope.inTransaction( (session) -> {
|
||||
final VersionedEntity entity = session.find( VersionedEntity.class, 1 );
|
||||
inspector.clear();
|
||||
session.remove( entity );
|
||||
} );
|
||||
checkEntityComments( inspector );
|
||||
}
|
||||
|
||||
private void checkEntityComments(SQLStatementInspector inspector) {
|
||||
assertThat( inspector.getSqlQueries() ).hasSize( 1 );
|
||||
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "VersionedEntity */" );
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void dropTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
session.createMutationQuery( "delete VersionedEntity" ).executeUpdate();
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity( name = "VersionedEntity" )
|
||||
@Table( name = "entity_table" )
|
||||
public static class VersionedEntity {
|
||||
@Id
|
||||
private Integer id;
|
||||
@Version
|
||||
private Integer version;
|
||||
@Basic
|
||||
private String name;
|
||||
|
||||
protected VersionedEntity() {
|
||||
// for use by Hibernate
|
||||
}
|
||||
|
||||
public VersionedEntity(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,11 +13,13 @@ import jakarta.persistence.Entity;
|
|||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
@Table( name = "user_accounts" )
|
||||
public class Account {
|
||||
private Integer id;
|
||||
|
||||
|
|
Loading…
Reference in New Issue