/* * 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.hql.spi.id; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.hibernate.JDBCException; import org.hibernate.dialect.Dialect; 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.AbstractRestrictableStatement; import org.hibernate.hql.internal.ast.tree.FromElement; import org.hibernate.param.ParameterSpecification; import org.hibernate.persister.entity.Queryable; /** * Base class for all strategies that select the ids to be updated/deleted prior to executing the update/delete operation. * * @author Vlad Mihalcea */ public abstract class AbstractIdsBulkIdHandler extends AbstractTableBasedBulkIdHandler { private final Queryable targetedPersister; private final String idSelect; private final List<ParameterSpecification> idSelectParameterSpecifications; public AbstractIdsBulkIdHandler( SessionFactoryImplementor sessionFactory, HqlSqlWalker walker) { super(sessionFactory, walker); final AbstractRestrictableStatement statement = (AbstractRestrictableStatement) walker.getAST(); final FromElement fromElement = statement.getFromClause().getFromElement(); this.targetedPersister = fromElement.getQueryable(); final ProcessedWhereClause processedWhereClause = processWhereClause( statement.getWhereClause() ); this.idSelectParameterSpecifications = processedWhereClause.getIdSelectParameterSpecifications(); final String bulkTargetAlias = fromElement.getTableAlias(); this.idSelect = generateIdSelect( bulkTargetAlias, processedWhereClause ).toStatementString(); } @Override public Queryable getTargetedQueryable() { return targetedPersister; } protected Dialect dialect() { return factory().getServiceRegistry().getService( JdbcServices.class ).getDialect(); } protected JDBCException convert( SQLException e, String message, String sql) { throw factory().getServiceRegistry().getService( JdbcServices.class ).getSqlExceptionHelper().convert( e, message, sql ); } protected List<Object[]> selectIds( SharedSessionContractImplementor session, QueryParameters queryParameters) { List<Object[]> ids = new ArrayList<>(); try { try (PreparedStatement ps = session.getJdbcCoordinator() .getStatementPreparer() .prepareStatement( idSelect, false )) { int position = 1; for ( ParameterSpecification parameterSpecification : idSelectParameterSpecifications ) { position += parameterSpecification.bind( ps, queryParameters, session, position ); } ResultSet rs = session .getJdbcCoordinator() .getResultSetReturn() .extract( ps ); while ( rs.next() ) { Object[] result = new Object[targetedPersister.getIdentifierColumnNames().length]; for ( String columnName : targetedPersister.getIdentifierColumnNames() ) { Object column = rs.getObject( columnName ); result[rs.findColumn( columnName ) - 1] = column; } ids.add( result ); } } } catch ( SQLException e ) { throw convert( e, "could not select ids for bulk operation", idSelect ); } return ids; } }