org.hibernate.hql.spi.id.cte.CteValuesListUpdateHandlerImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-core Show documentation
Show all versions of hibernate-core Show documentation
The core O/RM functionality as provided by Hibernate
The newest version!
/*
* 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 .
*/
package org.hibernate.hql.spi.id.cte;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.hql.internal.ast.HqlSqlWalker;
import org.hibernate.hql.internal.ast.tree.AssignmentSpecification;
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
import org.hibernate.param.ParameterSpecification;
import org.hibernate.sql.Update;
/**
* Bulk-id update handler that uses CTE and VALUES lists.
*
* @author Evandro Pires da Silva
* @author Vlad Mihalcea
*/
public class CteValuesListUpdateHandlerImpl
extends AbstractCteValuesListBulkIdHandler
implements MultiTableBulkIdStrategy.UpdateHandler {
private final String[] updates;
private final ParameterSpecification[][] assignmentParameterSpecifications;
public CteValuesListUpdateHandlerImpl(
SessionFactoryImplementor factory,
HqlSqlWalker walker) {
this( factory, walker, null, null );
}
public CteValuesListUpdateHandlerImpl(
SessionFactoryImplementor factory,
HqlSqlWalker walker,
String catalog,
String schema) {
super( factory, walker, catalog, schema );
String[] tableNames = getTargetedQueryable().getConstraintOrderedTableNameClosure();
String[][] columnNames = getTargetedQueryable().getContraintOrderedTableKeyColumnClosure();
String idSubselect = generateIdSubselect( getTargetedQueryable() );
updates = new String[tableNames.length];
assignmentParameterSpecifications = new ParameterSpecification[tableNames.length][];
for ( int tableIndex = 0; tableIndex < tableNames.length; tableIndex++ ) {
boolean affected = false;
final List parameterList = new ArrayList<>();
final Update update = new Update( factory.getServiceRegistry().getService( JdbcServices.class ).getDialect() )
.setTableName( tableNames[tableIndex] )
.setWhere( "(" + String.join( ", ", (CharSequence[]) columnNames[tableIndex] ) + ") in (" + idSubselect + ")" );
if ( factory().getSessionFactoryOptions().isCommentsEnabled() ) {
update.setComment( "bulk update" );
}
final List assignmentSpecifications = walker.getAssignmentSpecifications();
for ( AssignmentSpecification assignmentSpecification : assignmentSpecifications ) {
if ( assignmentSpecification.affectsTable( tableNames[tableIndex] ) ) {
affected = true;
update.appendAssignmentFragment( assignmentSpecification.getSqlAssignmentFragment() );
if ( assignmentSpecification.getParameters() != null ) {
Collections.addAll( parameterList, assignmentSpecification.getParameters() );
}
}
}
if ( affected ) {
updates[tableIndex] = update.toStatementString();
assignmentParameterSpecifications[tableIndex] = parameterList.toArray( new ParameterSpecification[parameterList.size()] );
}
}
}
@Override
public String[] getSqlStatements() {
return updates;
}
@Override
public int execute(
SharedSessionContractImplementor session,
QueryParameters queryParameters) {
CteValuesListBuilder values = prepareCteStatement( session, queryParameters );
if ( !values.getIds().isEmpty() ) {
// Start performing the updates
for ( int i = 0; i < updates.length; i++ ) {
String updateSuffix = updates[i];
if ( updateSuffix == null) {
continue;
}
String update = values.toStatement( updateSuffix );
try {
try (PreparedStatement ps = session
.getJdbcCoordinator().getStatementPreparer()
.prepareStatement( update, false )) {
int position = 1; // jdbc params are 1-based
for ( Object[] result : values.getIds() ) {
for ( Object column : result ) {
ps.setObject( position++, column );
}
}
if ( assignmentParameterSpecifications[i] != null ) {
for ( int x = 0; x < assignmentParameterSpecifications[i].length; x++ ) {
position += assignmentParameterSpecifications[i][x]
.bind( ps, queryParameters, session, position );
}
}
session
.getJdbcCoordinator().getResultSetReturn()
.executeUpdate( ps );
}
}
catch ( SQLException e ) {
throw convert(
e,
"error performing bulk update",
update
);
}
}
}
return values.getIds().size();
}
}