Package org.hibernate.hql.internal.ast.exec

Source Code of org.hibernate.hql.internal.ast.exec.DeleteExecutor

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*/
package org.hibernate.hql.internal.ast.exec;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.hql.internal.ast.HqlSqlWalker;
import org.hibernate.hql.internal.ast.SqlGenerator;
import org.hibernate.hql.internal.ast.tree.DeleteStatement;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.param.ParameterSpecification;
import org.hibernate.persister.collection.AbstractCollectionPersister;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.Delete;
import org.hibernate.type.CollectionType;
import org.hibernate.type.Type;

import org.jboss.logging.Logger;

import antlr.RecognitionException;
import antlr.collections.AST;


/**
* Provides deletions in addition to the basic SQL delete statement being executed.  Ex: cascading the delete into a
* many-to-many join table.
*
* @author Brett Meyer
*/
public class DeleteExecutor extends BasicExecutor {
  private static final Logger LOG = Logger.getLogger( DeleteExecutor.class );

  private final List<String> deletes = new ArrayList<String>();
  private List<ParameterSpecification> parameterSpecifications;

  public DeleteExecutor(HqlSqlWalker walker, Queryable persister) {
    super( walker, persister );
   
    final SessionFactoryImplementor factory = walker.getSessionFactoryHelper().getFactory();
    final Dialect dialect = factory.getDialect();
   
    try {
      final DeleteStatement deleteStatement = (DeleteStatement) walker.getAST();
     
      final String idSubselectWhere;
      if ( deleteStatement.hasWhereClause() ) {
        final AST whereClause = deleteStatement.getWhereClause();
        final SqlGenerator gen = new SqlGenerator( factory );
        gen.whereClause( whereClause );
        parameterSpecifications = gen.getCollectedParameters();
        idSubselectWhere = gen.getSQL().length() > 7 ? gen.getSQL() : "";
      }
      else {
        parameterSpecifications = new ArrayList<ParameterSpecification>();
        idSubselectWhere = "";
      }
     
      // If many-to-many, delete the FK row in the collection table.
      for ( Type type : persister.getPropertyTypes() ) {
        if ( type.isCollectionType() ) {
          final CollectionType cType = (CollectionType) type;
          final AbstractCollectionPersister cPersister = (AbstractCollectionPersister) factory
              .getCollectionPersister( cType.getRole() );
          if ( cPersister.isManyToMany() ) {
            if ( persister.getIdentifierColumnNames().length > 1
                && !dialect.supportsTuplesInSubqueries() ) {
              LOG.warn(
                  "This dialect is unable to cascade the delete into the many-to-many join table" +
                  " when the entity has multiple primary keys.  Either properly setup cascading on" +
                  " the constraints or manually clear the associations prior to deleting the entities."
              );
            }
            else {
              final String idSubselect = "(select "
                  + StringHelper.join( ", ", persister.getIdentifierColumnNames() ) + " from "
                  + persister.getTableName() + idSubselectWhere + ")";
              final String where = "(" + StringHelper.join( ", ", cPersister.getKeyColumnNames() )
                  + ") in " + idSubselect;
              final Delete delete = new Delete().setTableName( cPersister.getTableName() ).setWhere( where );
              if ( factory.getSettings().isCommentsEnabled() ) {
                delete.setComment( "delete FKs in join table" );
              }
              deletes.add( delete.toStatementString() );
            }
          }
        }
      }
    }
    catch (RecognitionException e) {
      throw new HibernateException( "Unable to delete the FKs in the join table!", e );
    }
  }
 
  @Override
  public int execute(QueryParameters parameters, SessionImplementor session) throws HibernateException {
    for (String delete : deletes) {
      doExecute( parameters, session, delete, parameterSpecifications );
    }
   
    // finally, execute the original sql statement
    return super.execute( parameters, session );
  }
}
TOP

Related Classes of org.hibernate.hql.internal.ast.exec.DeleteExecutor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.