1 56 package org.objectstyle.cayenne.access.jdbc; 57 58 import java.sql.Connection ; 59 import java.sql.PreparedStatement ; 60 import java.sql.ResultSet ; 61 import java.sql.SQLException ; 62 import java.sql.Statement ; 63 import java.util.Collections ; 64 import java.util.Iterator ; 65 import java.util.Map ; 66 67 import org.apache.log4j.Level; 68 import org.objectstyle.cayenne.CayenneException; 69 import org.objectstyle.cayenne.access.OperationObserver; 70 import org.objectstyle.cayenne.access.OptimisticLockException; 71 import org.objectstyle.cayenne.access.QueryLogger; 72 import org.objectstyle.cayenne.access.ResultIterator; 73 import org.objectstyle.cayenne.access.trans.BatchQueryBuilder; 74 import org.objectstyle.cayenne.access.trans.DeleteBatchQueryBuilder; 75 import org.objectstyle.cayenne.access.trans.InsertBatchQueryBuilder; 76 import org.objectstyle.cayenne.access.trans.UpdateBatchQueryBuilder; 77 import org.objectstyle.cayenne.dba.DbAdapter; 78 import org.objectstyle.cayenne.map.DbAttribute; 79 import org.objectstyle.cayenne.map.EntityResolver; 80 import org.objectstyle.cayenne.query.BatchQuery; 81 import org.objectstyle.cayenne.query.DeleteBatchQuery; 82 import org.objectstyle.cayenne.query.InsertBatchQuery; 83 import org.objectstyle.cayenne.query.UpdateBatchQuery; 84 85 89 public class BatchAction extends BaseSQLAction { 90 91 protected boolean batch; 92 protected BatchQuery query; 93 94 public BatchAction(BatchQuery batchQuery, DbAdapter adapter, 95 EntityResolver entityResolver) { 96 super(adapter, entityResolver); 97 this.query = batchQuery; 98 } 99 100 public boolean isBatch() { 101 return batch; 102 } 103 104 public void setBatch(boolean runningAsBatch) { 105 this.batch = runningAsBatch; 106 } 107 108 public void performAction(Connection connection, OperationObserver observer) 109 throws SQLException , Exception { 110 111 BatchQueryBuilder queryBuilder = createBuilder(); 112 boolean generatesKeys = hasGeneratedKeys(); 113 114 if (batch && !generatesKeys) { 115 runAsBatch(connection, queryBuilder, observer); 116 } 117 else { 118 runAsIndividualQueries(connection, queryBuilder, observer, generatesKeys); 119 } 120 } 121 122 protected BatchQueryBuilder createBuilder() throws CayenneException { 123 if (query instanceof InsertBatchQuery) { 124 return new InsertBatchQueryBuilder(getAdapter()); 125 } 126 else if (query instanceof UpdateBatchQuery) { 127 return new UpdateBatchQueryBuilder(getAdapter()); 128 } 129 else if (query instanceof DeleteBatchQuery) { 130 return new DeleteBatchQueryBuilder(getAdapter()); 131 } 132 else { 133 throw new CayenneException("Unsupported batch query: " + query); 134 } 135 } 136 137 protected void runAsBatch( 138 Connection con, 139 BatchQueryBuilder queryBuilder, 140 OperationObserver delegate) throws SQLException , Exception { 141 142 String queryStr = queryBuilder.createSqlString(query); 143 Level logLevel = query.getLoggingLevel(); 144 boolean isLoggable = QueryLogger.isLoggable(logLevel); 145 146 QueryLogger.logQuery(logLevel, queryStr, Collections.EMPTY_LIST); 148 149 query.reset(); 151 152 PreparedStatement statement = con.prepareStatement(queryStr); 153 try { 154 while (query.next()) { 155 156 if (isLoggable) { 157 QueryLogger.logQueryParameters(logLevel, "batch bind", queryBuilder 158 .getParameterValues(query)); 159 } 160 161 queryBuilder.bindParameters(statement, query); 162 statement.addBatch(); 163 } 164 165 int[] results = statement.executeBatch(); 167 delegate.nextBatchCount(query, results); 168 169 if (isLoggable) { 170 QueryLogger.logUpdateCount(logLevel, statement.getUpdateCount()); 171 } 172 } 173 finally { 174 try { 175 statement.close(); 176 } 177 catch (Exception e) { 178 } 179 } 180 } 181 182 185 protected void runAsIndividualQueries( 186 Connection connection, 187 BatchQueryBuilder queryBuilder, 188 OperationObserver delegate, 189 boolean generatesKeys) throws SQLException , Exception { 190 191 Level logLevel = query.getLoggingLevel(); 192 boolean isLoggable = QueryLogger.isLoggable(logLevel); 193 boolean useOptimisticLock = query.isUsingOptimisticLocking(); 194 195 String queryStr = queryBuilder.createSqlString(query); 196 197 QueryLogger.logQuery(logLevel, queryStr, Collections.EMPTY_LIST); 199 200 query.reset(); 202 203 PreparedStatement statement = (generatesKeys) ? connection 204 .prepareStatement(queryStr, Statement.RETURN_GENERATED_KEYS) : connection 205 .prepareStatement(queryStr); 206 try { 207 while (query.next()) { 208 if (isLoggable) { 209 QueryLogger.logQueryParameters(logLevel, "bind", queryBuilder 210 .getParameterValues(query)); 211 } 212 213 queryBuilder.bindParameters(statement, query); 214 215 int updated = statement.executeUpdate(); 216 if (useOptimisticLock && updated != 1) { 217 218 Map snapshot = Collections.EMPTY_MAP; 219 if (query instanceof UpdateBatchQuery) { 220 snapshot = ((UpdateBatchQuery) query).getCurrentQualifier(); 221 } 222 else if (query instanceof DeleteBatchQuery) { 223 snapshot = ((DeleteBatchQuery) query).getCurrentQualifier(); 224 } 225 226 throw new OptimisticLockException( 227 query.getDbEntity(), 228 queryStr, 229 snapshot); 230 } 231 232 delegate.nextCount(query, updated); 233 234 if (generatesKeys) { 235 processGeneratedKeys(statement, delegate); 236 } 237 238 if (isLoggable) { 239 QueryLogger.logUpdateCount(logLevel, updated); 240 } 241 } 242 } 243 finally { 244 try { 245 statement.close(); 246 } 247 catch (Exception e) { 248 } 249 } 250 } 251 252 255 protected boolean hasGeneratedKeys() { 256 if (!adapter.supportsGeneratedKeys()) { 258 return false; 259 } 260 261 if (query instanceof InsertBatchQuery) { 263 264 Iterator attributes = query.getDbEntity().getGeneratedAttributes().iterator(); 266 while (attributes.hasNext()) { 267 if (((DbAttribute) attributes.next()).isPrimaryKey()) { 268 return true; 269 } 270 } 271 } 272 273 return false; 274 } 275 276 279 protected void processGeneratedKeys(Statement statement, OperationObserver observer) 280 throws SQLException , CayenneException { 281 282 ResultSet keysRS = statement.getGeneratedKeys(); 283 RowDescriptor descriptor = new RowDescriptor(keysRS, getAdapter() 284 .getExtendedTypes()); 285 ResultIterator iterator = new JDBCResultIterator( 286 null, 287 null, 288 keysRS, 289 descriptor, 290 0); 291 292 observer.nextGeneratedDataRows(query, iterator); 293 } 294 } | Popular Tags |