1 19 20 package org.apache.cayenne.access.jdbc; 21 22 import java.sql.Connection ; 23 import java.sql.PreparedStatement ; 24 import java.sql.ResultSet ; 25 import java.sql.SQLException ; 26 import java.sql.Statement ; 27 import java.util.Collection ; 28 import java.util.Collections ; 29 import java.util.Iterator ; 30 import java.util.Map ; 31 32 import org.apache.cayenne.CayenneException; 33 import org.apache.cayenne.access.OperationObserver; 34 import org.apache.cayenne.access.OptimisticLockException; 35 import org.apache.cayenne.access.QueryLogger; 36 import org.apache.cayenne.access.ResultIterator; 37 import org.apache.cayenne.access.trans.BatchQueryBuilder; 38 import org.apache.cayenne.access.trans.DeleteBatchQueryBuilder; 39 import org.apache.cayenne.access.trans.InsertBatchQueryBuilder; 40 import org.apache.cayenne.access.trans.UpdateBatchQueryBuilder; 41 import org.apache.cayenne.dba.DbAdapter; 42 import org.apache.cayenne.dba.TypesMapping; 43 import org.apache.cayenne.map.DbAttribute; 44 import org.apache.cayenne.map.EntityResolver; 45 import org.apache.cayenne.query.BatchQuery; 46 import org.apache.cayenne.query.DeleteBatchQuery; 47 import org.apache.cayenne.query.InsertBatchQuery; 48 import org.apache.cayenne.query.UpdateBatchQuery; 49 50 54 public class BatchAction extends BaseSQLAction { 55 56 protected boolean batch; 57 protected BatchQuery query; 58 protected RowDescriptor keyRowDescriptor; 59 60 public BatchAction(BatchQuery batchQuery, DbAdapter adapter, 61 EntityResolver entityResolver) { 62 super(adapter, entityResolver); 63 this.query = batchQuery; 64 } 65 66 public boolean isBatch() { 67 return batch; 68 } 69 70 public void setBatch(boolean runningAsBatch) { 71 this.batch = runningAsBatch; 72 } 73 74 public void performAction(Connection connection, OperationObserver observer) 75 throws SQLException , Exception { 76 77 BatchQueryBuilder queryBuilder = createBuilder(); 78 boolean generatesKeys = hasGeneratedKeys(); 79 80 if (batch && !generatesKeys) { 81 runAsBatch(connection, queryBuilder, observer); 82 } 83 else { 84 runAsIndividualQueries(connection, queryBuilder, observer, generatesKeys); 85 } 86 } 87 88 protected BatchQueryBuilder createBuilder() throws CayenneException { 89 if (query instanceof InsertBatchQuery) { 90 return new InsertBatchQueryBuilder(getAdapter()); 91 } 92 else if (query instanceof UpdateBatchQuery) { 93 return new UpdateBatchQueryBuilder(getAdapter()); 94 } 95 else if (query instanceof DeleteBatchQuery) { 96 return new DeleteBatchQueryBuilder(getAdapter()); 97 } 98 else { 99 throw new CayenneException("Unsupported batch query: " + query); 100 } 101 } 102 103 protected void runAsBatch( 104 Connection con, 105 BatchQueryBuilder queryBuilder, 106 OperationObserver delegate) throws SQLException , Exception { 107 108 String queryStr = queryBuilder.createSqlString(query); 109 boolean isLoggable = QueryLogger.isLoggable(); 110 111 QueryLogger.logQuery(queryStr, Collections.EMPTY_LIST); 113 114 query.reset(); 116 117 PreparedStatement statement = con.prepareStatement(queryStr); 118 try { 119 while (query.next()) { 120 121 if (isLoggable) { 122 QueryLogger.logQueryParameters("batch bind", queryBuilder 123 .getParameterValues(query)); 124 } 125 126 queryBuilder.bindParameters(statement, query); 127 statement.addBatch(); 128 } 129 130 int[] results = statement.executeBatch(); 132 delegate.nextBatchCount(query, results); 133 134 if (isLoggable) { 135 int totalUpdateCount = 0; 136 for (int i = 0; i < results.length; i++) { 137 138 if (results[i] < 0) { 140 totalUpdateCount = Statement.SUCCESS_NO_INFO; 141 break; 142 } 143 144 totalUpdateCount += results[i]; 145 } 146 147 QueryLogger.logUpdateCount(totalUpdateCount); 148 } 149 } 150 finally { 151 try { 152 statement.close(); 153 } 154 catch (Exception e) { 155 } 156 } 157 } 158 159 162 protected void runAsIndividualQueries( 163 Connection connection, 164 BatchQueryBuilder queryBuilder, 165 OperationObserver delegate, 166 boolean generatesKeys) throws SQLException , Exception { 167 168 boolean isLoggable = QueryLogger.isLoggable(); 169 boolean useOptimisticLock = query.isUsingOptimisticLocking(); 170 171 String queryStr = queryBuilder.createSqlString(query); 172 173 QueryLogger.logQuery(queryStr, Collections.EMPTY_LIST); 175 176 query.reset(); 178 179 PreparedStatement statement = (generatesKeys) ? connection.prepareStatement( 180 queryStr, 181 Statement.RETURN_GENERATED_KEYS) : connection.prepareStatement(queryStr); 182 try { 183 while (query.next()) { 184 if (isLoggable) { 185 QueryLogger.logQueryParameters("bind", queryBuilder 186 .getParameterValues(query)); 187 } 188 189 queryBuilder.bindParameters(statement, query); 190 191 int updated = statement.executeUpdate(); 192 if (useOptimisticLock && updated != 1) { 193 194 Map snapshot = Collections.EMPTY_MAP; 195 if (query instanceof UpdateBatchQuery) { 196 snapshot = ((UpdateBatchQuery) query).getCurrentQualifier(); 197 } 198 else if (query instanceof DeleteBatchQuery) { 199 snapshot = ((DeleteBatchQuery) query).getCurrentQualifier(); 200 } 201 202 throw new OptimisticLockException( 203 query.getDbEntity(), 204 queryStr, 205 snapshot); 206 } 207 208 delegate.nextCount(query, updated); 209 210 if (generatesKeys) { 211 processGeneratedKeys(statement, delegate); 212 } 213 214 if (isLoggable) { 215 QueryLogger.logUpdateCount(updated); 216 } 217 } 218 } 219 finally { 220 try { 221 statement.close(); 222 } 223 catch (Exception e) { 224 } 225 } 226 } 227 228 231 protected boolean hasGeneratedKeys() { 232 if (!adapter.supportsGeneratedKeys()) { 234 return false; 235 } 236 237 if (query instanceof InsertBatchQuery) { 239 240 Iterator attributes = query.getDbEntity().getGeneratedAttributes().iterator(); 242 while (attributes.hasNext()) { 243 if (((DbAttribute) attributes.next()).isPrimaryKey()) { 244 return true; 245 } 246 } 247 } 248 249 return false; 250 } 251 252 255 protected void processGeneratedKeys(Statement statement, OperationObserver observer) 256 throws SQLException , CayenneException { 257 258 ResultSet keysRS = statement.getGeneratedKeys(); 259 260 266 if (this.keyRowDescriptor == null) { 267 Collection generated = query.getDbEntity().getGeneratedAttributes(); 269 if (generated.size() == 1) { 270 DbAttribute key = (DbAttribute) generated.iterator().next(); 271 272 ColumnDescriptor[] columns = new ColumnDescriptor[1]; 273 274 columns[0] = new ColumnDescriptor(keysRS.getMetaData(), 1); 277 columns[0].setJdbcType(key.getType()); 278 columns[0].setJavaClass(TypesMapping.getJavaBySqlType(key.getType())); 279 keyRowDescriptor = new RowDescriptor(columns, getAdapter() 280 .getExtendedTypes()); 281 } 282 else { 283 keyRowDescriptor = new RowDescriptor(keysRS, getAdapter() 284 .getExtendedTypes()); 285 } 286 } 287 288 ResultIterator iterator = new JDBCResultIterator( 289 null, 290 null, 291 keysRS, 292 keyRowDescriptor, 293 0); 294 295 observer.nextGeneratedDataRows(query, iterator); 296 } 297 } 298 | Popular Tags |