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.ArrayList ; 28 import java.util.Arrays ; 29 import java.util.Collection ; 30 import java.util.Collections ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 35 import org.apache.commons.collections.IteratorUtils; 36 import org.apache.cayenne.CayenneException; 37 import org.apache.cayenne.access.OperationObserver; 38 import org.apache.cayenne.access.QueryLogger; 39 import org.apache.cayenne.access.types.ExtendedTypeMap; 40 import org.apache.cayenne.dba.DbAdapter; 41 import org.apache.cayenne.query.SQLAction; 42 import org.apache.cayenne.query.SQLTemplate; 43 import org.apache.cayenne.util.Util; 44 45 51 public class SQLTemplateAction implements SQLAction { 52 53 protected DbAdapter adapter; 54 protected SQLTemplate query; 55 56 public SQLTemplateAction(SQLTemplate query, DbAdapter adapter) { 57 this.query = query; 58 this.adapter = adapter; 59 } 60 61 64 public DbAdapter getAdapter() { 65 return adapter; 66 } 67 68 72 public void performAction(Connection connection, OperationObserver callback) 73 throws SQLException , Exception { 74 75 String template = extractTemplateString(); 76 77 if (template == null) { 79 throw new CayenneException("No template string configured for adapter " 80 + getAdapter().getClass().getName()); 81 } 82 83 boolean loggable = QueryLogger.isLoggable(); 84 int size = query.parametersSize(); 85 86 SQLTemplateProcessor templateProcessor = new SQLTemplateProcessor(); 87 88 int batchSize = (size > 0) ? size : 1; 91 92 List counts = new ArrayList (batchSize); 93 Iterator it = (size > 0) ? query.parametersIterator() : IteratorUtils 94 .singletonIterator(Collections.EMPTY_MAP); 95 for (int i = 0; i < batchSize; i++) { 96 Map nextParameters = (Map ) it.next(); 97 98 SQLStatement compiled = templateProcessor.processTemplate( 99 template, 100 nextParameters); 101 102 if (loggable) { 103 QueryLogger.logQuery(compiled.getSql(), Arrays.asList(compiled 104 .getBindings())); 105 } 106 107 execute(connection, callback, compiled, counts); 108 } 109 110 if (counts != null) { 113 int[] ints = new int[counts.size()]; 114 for (int i = 0; i < ints.length; i++) { 115 ints[i] = ((Integer ) counts.get(i)).intValue(); 116 } 117 118 callback.nextBatchCount(query, ints); 119 } 120 } 121 122 protected void execute( 123 Connection connection, 124 OperationObserver callback, 125 SQLStatement compiled, 126 Collection updateCounts) throws SQLException , Exception { 127 128 long t1 = System.currentTimeMillis(); 129 boolean iteratedResult = callback.isIteratedResult(); 130 PreparedStatement statement = connection.prepareStatement(compiled.getSql()); 131 try { 132 bind(statement, compiled.getBindings()); 133 134 boolean isResultSet = statement.execute(); 136 boolean firstIteration = true; 137 while (true) { 138 139 if (firstIteration) { 140 firstIteration = false; 141 } 142 else { 143 isResultSet = statement.getMoreResults(); 144 } 145 146 if (isResultSet) { 147 148 ResultSet resultSet = statement.getResultSet(); 149 150 if (resultSet != null) { 151 152 try { 153 processSelectResult( 154 compiled, 155 connection, 156 statement, 157 resultSet, 158 callback, 159 t1); 160 } 161 finally { 162 if (iteratedResult) { 163 break; 164 } 165 else { 166 resultSet.close(); 167 } 168 } 169 } 170 } 171 else { 172 int updateCount = statement.getUpdateCount(); 173 if (updateCount == -1) { 174 break; 175 } 176 177 updateCounts.add(new Integer (updateCount)); 178 QueryLogger.logUpdateCount(updateCount); 179 } 180 } 181 } 182 finally { 183 if (!iteratedResult) { 184 statement.close(); 185 } 186 } 187 } 188 189 protected void processSelectResult( 190 SQLStatement compiled, 191 Connection connection, 192 Statement statement, 193 ResultSet resultSet, 194 OperationObserver callback, 195 long startTime) throws Exception { 196 197 boolean iteratedResult = callback.isIteratedResult(); 198 199 ExtendedTypeMap types = adapter.getExtendedTypes(); 200 RowDescriptor descriptor = (compiled.getResultColumns().length > 0) 201 ? new RowDescriptor(compiled.getResultColumns(), types) 202 : new RowDescriptor(resultSet, types); 203 204 if (query.getColumnNamesCapitalization() != null) { 205 if (SQLTemplate.LOWERCASE_COLUMN_NAMES.equals(query 206 .getColumnNamesCapitalization())) { 207 descriptor.forceLowerCaseColumnNames(); 208 } 209 else if (SQLTemplate.UPPERCASE_COLUMN_NAMES.equals(query 210 .getColumnNamesCapitalization())) { 211 descriptor.forceUpperCaseColumnNames(); 212 } 213 } 214 215 JDBCResultIterator result = new JDBCResultIterator( 216 connection, 217 statement, 218 resultSet, 219 descriptor, 220 query.getFetchLimit()); 221 222 if (!iteratedResult) { 223 List resultRows = result.dataRows(false); 224 QueryLogger.logSelectCount(resultRows.size(), System.currentTimeMillis() 225 - startTime); 226 227 callback.nextDataRows(query, resultRows); 228 } 229 else { 230 try { 231 result.setClosingConnection(true); 232 callback.nextDataRows(query, result); 233 } 234 catch (Exception ex) { 235 result.close(); 236 throw ex; 237 } 238 } 239 } 240 241 247 protected String extractTemplateString() { 248 String sql = query.getTemplate(getAdapter().getClass().getName()); 249 250 return Util.stripLineBreaks(sql, " "); 253 } 254 255 258 protected void bind(PreparedStatement preparedStatement, ParameterBinding[] bindings) 259 throws SQLException , Exception { 260 if (bindings.length > 0) { 262 int len = bindings.length; 263 for (int i = 0; i < len; i++) { 264 adapter.bindParameter( 265 preparedStatement, 266 bindings[i].getValue(), 267 i + 1, 268 bindings[i].getJdbcType(), 269 bindings[i].getPrecision()); 270 } 271 } 272 } 273 274 279 public boolean isRemovingLineBreaks() { 280 return true; 281 } 282 283 286 public void setRemovingLineBreaks(boolean removingLineBreaks) { 287 288 } 289 290 293 public SQLTemplate getQuery() { 294 return query; 295 } 296 } 297 | Popular Tags |