1 package org.hibernate.hql.ast.exec; 3 4 import java.sql.PreparedStatement ; 5 import java.sql.SQLException ; 6 import java.util.Iterator ; 7 8 import org.hibernate.HibernateException; 9 import org.hibernate.engine.QueryParameters; 10 import org.hibernate.engine.SessionImplementor; 11 import org.hibernate.exception.JDBCExceptionHelper; 12 import org.hibernate.hql.ast.HqlSqlWalker; 13 import org.hibernate.hql.ast.tree.DeleteStatement; 14 import org.hibernate.hql.ast.tree.FromElement; 15 import org.hibernate.param.ParameterSpecification; 16 import org.hibernate.persister.entity.Queryable; 17 import org.hibernate.sql.Delete; 18 import org.hibernate.util.StringHelper; 19 20 import org.apache.commons.logging.Log; 21 import org.apache.commons.logging.LogFactory; 22 23 28 public class MultiTableDeleteExecutor extends AbstractStatementExecutor { 29 private static final Log log = LogFactory.getLog( MultiTableDeleteExecutor.class ); 30 31 private final DeleteStatement deleteStatement; 32 private final Queryable persister; 33 private final String idInsertSelect; 34 private final String [] deletes; 35 36 public MultiTableDeleteExecutor(HqlSqlWalker walker) { 37 super( walker, log ); 38 39 this.deleteStatement = ( DeleteStatement ) walker.getAST(); 40 41 FromElement fromElement = deleteStatement.getFromClause().getFromElement(); 42 this.persister = fromElement.getQueryable(); 43 44 this.idInsertSelect = generateIdInsertSelect( persister, ( ( DeleteStatement ) walker.getAST() ).getWhereClause() ); 45 log.trace( "Generated ID-INSERT-SELECT SQL (multi-table delete) : " + idInsertSelect ); 46 47 String [] tableNames = persister.getConstraintOrderedTableNameClosure(); 48 String [][] columnNames = persister.getContraintOrderedTableKeyColumnClosure(); 49 String idSubselect = generateIdSubselect( persister ); 50 51 deletes = new String [tableNames.length]; 52 for ( int i = tableNames.length - 1; i >= 0; i-- ) { 53 final Delete delete = new Delete() 58 .setTableName( tableNames[i] ) 59 .setWhere( "(" + StringHelper.join( ", ", columnNames[i] ) + ") IN (" + idSubselect + ")" ); 60 if ( getFactory().getSettings().isCommentsEnabled() && getFactory().getDialect().supportsCommentOn() ) { 61 delete.setComment( "bulk delete" ); 62 } 63 64 deletes[i] = delete.toStatementString(); 65 } 66 } 67 68 public int execute(QueryParameters parameters, SessionImplementor session) throws HibernateException { 69 coordinateSharedCacheCleanup( session ); 70 71 createTemporaryTableIfNecessary( persister, session ); 72 73 try { 74 PreparedStatement ps = null; 76 int resultCount = 0; 77 try { 78 try { 79 ps = session.getBatcher().prepareStatement( idInsertSelect ); 80 Iterator paramSpecifications = getWalker().getParameters().iterator(); 81 int pos = 1; 82 while ( paramSpecifications.hasNext() ) { 83 final ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecifications.next(); 84 pos += paramSpec.bind( ps, parameters, session, pos ); 85 } 86 resultCount = ps.executeUpdate(); 87 } 88 finally { 89 if ( ps != null ) { 90 session.getBatcher().closeStatement( ps ); 91 } 92 } 93 } 94 catch( SQLException e ) { 95 throw JDBCExceptionHelper.convert( 96 getFactory().getSQLExceptionConverter(), 97 e, 98 "could not insert/select ids for bulk delete", 99 idInsertSelect 100 ); 101 } 102 103 for ( int i = 0; i < deletes.length; i++ ) { 105 try { 106 try { 107 ps = session.getBatcher().prepareStatement( deletes[i] ); 108 ps.executeUpdate(); 109 } 110 finally { 111 if ( ps != null ) { 112 session.getBatcher().closeStatement( ps ); 113 } 114 } 115 } 116 catch( SQLException e ) { 117 throw JDBCExceptionHelper.convert( 118 getFactory().getSQLExceptionConverter(), 119 e, 120 "error performing bulk delete", 121 deletes[i] 122 ); 123 } 124 } 125 126 return resultCount; 127 } 128 finally { 129 dropTemporaryTableIfNecessary( persister, session ); 130 } 131 } 132 133 protected Queryable[] getAffectedQueryables() { 134 return new Queryable[] { persister }; 135 } 136 } 137 | Popular Tags |