1 package org.hibernate.hql.ast.exec; 3 4 import java.sql.PreparedStatement ; 5 import java.sql.SQLException ; 6 import java.util.ArrayList ; 7 import java.util.Iterator ; 8 import java.util.List ; 9 10 import org.hibernate.HibernateException; 11 import org.hibernate.engine.QueryParameters; 12 import org.hibernate.engine.SessionImplementor; 13 import org.hibernate.exception.JDBCExceptionHelper; 14 import org.hibernate.hql.ast.HqlSqlWalker; 15 import org.hibernate.hql.ast.tree.AssignmentSpecification; 16 import org.hibernate.hql.ast.tree.FromElement; 17 import org.hibernate.hql.ast.tree.UpdateStatement; 18 import org.hibernate.param.ParameterSpecification; 19 import org.hibernate.persister.entity.Queryable; 20 import org.hibernate.sql.Update; 21 import org.hibernate.util.StringHelper; 22 23 import org.apache.commons.logging.Log; 24 import org.apache.commons.logging.LogFactory; 25 26 31 public class MultiTableUpdateExecutor extends AbstractStatementExecutor { 32 private static final Log log = LogFactory.getLog( MultiTableUpdateExecutor.class ); 33 34 private final UpdateStatement updateStatement; 35 private final Queryable persister; 36 private final String idInsertSelect; 37 private final String [] updates; 38 private final ParameterSpecification[][] hqlParameters; 39 40 public MultiTableUpdateExecutor(HqlSqlWalker walker) { 41 super( walker, log ); 42 43 this.updateStatement = ( UpdateStatement ) walker.getAST(); 44 FromElement fromElement = updateStatement.getFromClause().getFromElement(); 45 this.persister = fromElement.getQueryable(); 46 47 this.idInsertSelect = generateIdInsertSelect( persister, updateStatement.getWhereClause() ); 48 log.trace( "Generated ID-INSERT-SELECT SQL (multi-table update) : " + idInsertSelect ); 49 50 String [] tableNames = persister.getConstraintOrderedTableNameClosure(); 51 String [][] columnNames = persister.getContraintOrderedTableKeyColumnClosure(); 52 53 String idSubselect = generateIdSubselect( persister ); 54 List assignmentSpecifications = walker.getAssignmentSpecifications(); 55 56 Iterator itr = null; 57 updates = new String [tableNames.length]; 58 hqlParameters = new ParameterSpecification[tableNames.length][]; 59 for ( int tableIndex = 0; tableIndex < tableNames.length; tableIndex++ ) { 60 boolean affected = false; 61 List parameterList = new ArrayList (); 62 Update update = new Update() 63 .setTableName( tableNames[tableIndex] ) 64 .setWhere( "(" + StringHelper.join( ", ", columnNames[tableIndex] ) + ") IN (" + idSubselect + ")" ); 65 if ( getFactory().getSettings().isCommentsEnabled() && getFactory().getDialect().supportsCommentOn() ) { 66 update.setComment( "bulk update" ); 67 } 68 itr = assignmentSpecifications.iterator(); 69 while ( itr.hasNext() ) { 70 final AssignmentSpecification specification = ( AssignmentSpecification ) itr.next(); 71 if ( specification.affectsTable( tableNames[tableIndex] ) ) { 72 affected = true; 73 update.appendAssignmentFragment( specification.getSqlAssignmentFragment() ); 74 if ( specification.getParameters() != null ) { 75 for ( int paramIndex = 0; paramIndex < specification.getParameters().length; paramIndex++ ) { 76 parameterList.add( specification.getParameters()[paramIndex] ); 77 } 78 } 79 } 80 } 81 if ( affected ) { 82 updates[tableIndex] = update.toStatementString(); 83 hqlParameters[tableIndex] = ( ParameterSpecification[] ) parameterList.toArray( new ParameterSpecification[0] ); 84 } 85 } 86 } 87 88 public Queryable getAffectedQueryable() { 89 return persister; 90 } 91 92 public int execute(QueryParameters parameters, SessionImplementor session) throws HibernateException { 93 coordinateSharedCacheCleanup( session ); 94 95 createTemporaryTableIfNecessary( persister, session ); 96 97 try { 98 PreparedStatement ps = null; 100 int resultCount = 0; 101 try { 102 try { 103 ps = session.getBatcher().prepareStatement( idInsertSelect ); 104 int parameterStart = getWalker().getNumberOfParametersInSetClause(); 105 List allParams = getWalker().getParameters(); 106 Iterator whereParams = allParams.subList( parameterStart, allParams.size() ).iterator(); 107 int sum = 1; while ( whereParams.hasNext() ) { 109 sum += ( ( ParameterSpecification ) whereParams.next() ).bind( ps, parameters, session, sum ); 110 } 111 resultCount = ps.executeUpdate(); 112 } 113 finally { 114 if ( ps != null ) { 115 session.getBatcher().closeStatement( ps ); 116 } 117 } 118 } 119 catch( SQLException e ) { 120 throw JDBCExceptionHelper.convert( 121 getFactory().getSQLExceptionConverter(), 122 e, 123 "could not insert/select ids for bulk update", 124 idInsertSelect 125 ); 126 } 127 128 for ( int i = 0; i < updates.length; i++ ) { 130 if ( updates[i] == null ) { 131 continue; 132 } 133 try { 134 try { 135 ps = session.getBatcher().prepareStatement( updates[i] ); 136 if ( hqlParameters[i] != null ) { 137 int position = 1; for ( int x = 0; x < hqlParameters[i].length; x++ ) { 139 position += hqlParameters[i][x].bind( ps, parameters, session, position ); 140 } 141 } 142 ps.executeUpdate(); 143 } 144 finally { 145 if ( ps != null ) { 146 session.getBatcher().closeStatement( ps ); 147 } 148 } 149 } 150 catch( SQLException e ) { 151 throw JDBCExceptionHelper.convert( 152 getFactory().getSQLExceptionConverter(), 153 e, 154 "error performing bulk update", 155 updates[i] 156 ); 157 } 158 } 159 160 return resultCount; 161 } 162 finally { 163 dropTemporaryTableIfNecessary( persister, session ); 164 } 165 } 166 167 protected Queryable[] getAffectedQueryables() { 168 return new Queryable[] { persister }; 169 } 170 } 171 | Popular Tags |