HHH-15393 - Improve write-paths to use mapping model
This commit is contained in:
parent
3abc8c940a
commit
175fe0e44d
|
@ -188,6 +188,8 @@ public class ResultSetReturnImpl implements ResultSetReturn {
|
|||
|
||||
@Override
|
||||
public int executeUpdate(PreparedStatement statement) {
|
||||
assert statement != null;
|
||||
|
||||
long executeStartNanos = 0;
|
||||
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
|
||||
executeStartNanos = System.nanoTime();
|
||||
|
|
|
@ -75,7 +75,7 @@ public abstract class AbstractSelectingDelegate implements InsertGeneratedIdenti
|
|||
jdbcServices.getSqlStatementLogger().logStatement( insertStatementDetails.getSqlString() );
|
||||
jdbcValueBindings.beforeStatement( insertStatementDetails, session );
|
||||
|
||||
final PreparedStatement insertStatement = insertStatementDetails.getStatement();
|
||||
final PreparedStatement insertStatement = insertStatementDetails.resolveStatement();
|
||||
jdbcCoordinator.getResultSetReturn().executeUpdate( insertStatement );
|
||||
|
||||
// the insert is complete, select the generated id...
|
||||
|
|
|
@ -45,6 +45,11 @@ public abstract class AbstractTableDelete extends AbstractRestrictedTableMutatio
|
|||
super( mutatingTable, mutationTarget, sqlComment, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLoggableName() {
|
||||
return "TableDelete";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expectation getExpectation() {
|
||||
return getMutatingTable().getTableMapping().getDeleteDetails().getExpectation();
|
||||
|
|
|
@ -45,6 +45,11 @@ public abstract class AbstractTableInsert extends AbstractTableMutation<JdbcInse
|
|||
this.valueBindings = valueBindings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLoggableName() {
|
||||
return "TableInsert";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expectation getExpectation() {
|
||||
return getMutatingTable().getTableMapping().getInsertDetails().getExpectation();
|
||||
|
|
|
@ -44,6 +44,18 @@ public abstract class AbstractTableMutation<O extends MutationOperation>
|
|||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final String type = isCustomSql() ? "custom-sql" : "generated";
|
||||
return getLoggableName() + "(" + getMutationTarget().getRolePath() + " : " + type + ")";
|
||||
}
|
||||
|
||||
public boolean isCustomSql() {
|
||||
return this instanceof CustomSqlMutation;
|
||||
}
|
||||
|
||||
protected abstract String getLoggableName();
|
||||
|
||||
@Override
|
||||
public MutatingTableReference getMutatingTable() {
|
||||
return mutatingTable;
|
||||
|
|
|
@ -54,6 +54,11 @@ public abstract class AbstractTableUpdate<O extends MutationOperation>
|
|||
this.valueBindings = valueBindings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLoggableName() {
|
||||
return "TableUpdate";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expectation getExpectation() {
|
||||
return getMutatingTable().getTableMapping().getUpdateDetails().getExpectation();
|
||||
|
|
|
@ -34,6 +34,11 @@ public class TableDeleteCustomSql extends AbstractTableDelete implements CustomS
|
|||
super( mutatingTable, mutationTarget, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomSql() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomSql() {
|
||||
return getMutatingTable().getTableMapping().getDeleteDetails().getCustomSql();
|
||||
|
|
|
@ -28,6 +28,11 @@ public class TableDeleteStandard extends AbstractTableDelete {
|
|||
super( mutatingTable, mutationTarget, keyRestrictionBindings, optLockRestrictionBindings, parameters );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomSql() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallable() {
|
||||
return false;
|
||||
|
|
|
@ -37,6 +37,11 @@ public class TableInsertCustomSql extends AbstractTableInsert implements CustomS
|
|||
super( mutatingTable, mutationTarget, parameters, valueBindings );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomSql() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomSql() {
|
||||
return getMutatingTable().getTableMapping().getInsertDetails().getCustomSql();
|
||||
|
|
|
@ -36,6 +36,11 @@ public class TableInsertStandard extends AbstractTableInsert {
|
|||
this.returningColumns = returningColumns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomSql() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ColumnReference> getReturningColumns() {
|
||||
return returningColumns;
|
||||
|
|
|
@ -37,6 +37,11 @@ public class TableUpdateCustomSql
|
|||
super( mutatingTable, mutationTarget, parameters, valueBindings, keyRestrictionBindings, optLockRestrictionBindings );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomSql() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomSql() {
|
||||
return getMutatingTable().getTableMapping().getUpdateDetails().getCustomSql();
|
||||
|
|
|
@ -43,6 +43,16 @@ public class TableUpdateNoSet
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLoggableName() {
|
||||
return "TableUpdateNoSet";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomSql() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker walker) {
|
||||
}
|
||||
|
|
|
@ -44,6 +44,11 @@ public class TableUpdateStandard extends AbstractTableUpdate<JdbcMutationOperati
|
|||
this.whereFragment = whereFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomSql() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallable() {
|
||||
return false;
|
||||
|
|
|
@ -65,6 +65,16 @@ public class TableUpsert
|
|||
this.valueBindings = valueBindings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLoggableName() {
|
||||
return "TableUpsert";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomSql() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMutationTarget getMutationTarget() {
|
||||
return (EntityMutationTarget) super.getMutationTarget();
|
||||
|
|
|
@ -6,20 +6,100 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.dialect;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.HANAColumnStoreDialect;
|
||||
import org.hibernate.engine.jdbc.mutation.MutationExecutor;
|
||||
import org.hibernate.engine.jdbc.mutation.group.PreparedStatementDetails;
|
||||
import org.hibernate.engine.jdbc.mutation.spi.MutationExecutorService;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.id.PostInsertIdentityPersister;
|
||||
import org.hibernate.persister.entity.SingleTableEntityPersister;
|
||||
import org.hibernate.sql.model.MutationOperationGroup;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||
import org.hibernate.testing.transaction.TransactionUtil2;
|
||||
import org.junit.Test;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class HANADialectTestCase extends BaseUnitTestCase {
|
||||
@Test
|
||||
public void testSqlGeneratedForIdentityInsertNoColumns() {
|
||||
ServiceRegistryScope.using(
|
||||
() -> new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.DIALECT, HANAColumnStoreDialect.class )
|
||||
.build(),
|
||||
(registryScope) -> {
|
||||
final StandardServiceRegistry registry = registryScope.getRegistry();
|
||||
final MetadataSources metadataSources = new MetadataSources( registry );
|
||||
metadataSources.addAnnotatedClass( EntityWithIdentity.class );
|
||||
|
||||
try ( SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) metadataSources.buildMetadata().buildSessionFactory() ) {
|
||||
final PostInsertIdentityPersister entityDescriptor = (PostInsertIdentityPersister) sessionFactory.getRuntimeMetamodels()
|
||||
.getMappingMetamodel()
|
||||
.getEntityDescriptor( EntityWithIdentity.class );
|
||||
final MutationOperationGroup staticInsertGroup = ( (SingleTableEntityPersister) entityDescriptor ).getInsertCoordinator().getStaticInsertGroup();
|
||||
|
||||
final MutationExecutorService mutationExecutorService = sessionFactory
|
||||
.getServiceRegistry()
|
||||
.getService( MutationExecutorService.class );
|
||||
|
||||
TransactionUtil2.inTransaction(
|
||||
sessionFactory,
|
||||
(session) -> {
|
||||
final MutationExecutor mutationExecutor = mutationExecutorService.createExecutor(
|
||||
() -> null,
|
||||
staticInsertGroup,
|
||||
session
|
||||
);
|
||||
final PreparedStatementDetails statementDetails = mutationExecutor.getPreparedStatementDetails( "EntityWithIdentity" );
|
||||
assertThat( statementDetails.getSqlString() ).isEqualTo( "insert into EntityWithIdentity values ( )" );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intentionally one of those silly cases where a table has only an id column.
|
||||
* Here especially, since it is an IDENTITY the insert will have no columns at all.
|
||||
*/
|
||||
@Entity( name = "EntityWithIdentity" )
|
||||
@Table( name = "EntityWithIdentity" )
|
||||
public static class EntityWithIdentity {
|
||||
@Id @GeneratedValue( strategy = GenerationType.IDENTITY )
|
||||
private Integer id;
|
||||
|
||||
private EntityWithIdentity() {
|
||||
// for use by Hibernate
|
||||
}
|
||||
|
||||
public EntityWithIdentity(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-13239")
|
||||
|
|
Loading…
Reference in New Issue