1 package org.apache.torque.util;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.io.Serializable;
23 import java.math.BigDecimal;
24 import java.sql.Connection;
25 import java.sql.PreparedStatement;
26 import java.sql.ResultSet;
27 import java.sql.SQLException;
28 import java.sql.Statement;
29 import java.sql.Types;
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.Map;
33
34 import org.apache.commons.lang.StringUtils;
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.torque.Column;
38 import org.apache.torque.Database;
39 import org.apache.torque.TooManyRowsException;
40 import org.apache.torque.Torque;
41 import org.apache.torque.TorqueException;
42 import org.apache.torque.adapter.Adapter;
43 import org.apache.torque.adapter.IDMethod;
44 import org.apache.torque.criteria.FromElement;
45 import org.apache.torque.map.ColumnMap;
46 import org.apache.torque.map.MapHelper;
47 import org.apache.torque.map.TableMap;
48 import org.apache.torque.oid.IdGenerator;
49 import org.apache.torque.om.NumberKey;
50 import org.apache.torque.om.ObjectKey;
51 import org.apache.torque.om.SimpleKey;
52 import org.apache.torque.om.StringKey;
53 import org.apache.torque.om.mapper.RecordMapper;
54 import org.apache.torque.sql.Query;
55 import org.apache.torque.sql.SqlBuilder;
56
57 /**
58 * This is the base class for all Peer classes in the system. Peer
59 * classes are responsible for isolating all of the database access
60 * for a specific business object. They execute all of the SQL
61 * against the database. Over time this class has grown to include
62 * utility methods which ease execution of cross-database queries and
63 * the implementation of concrete Peers.
64 *
65 * @param <T> The data object class for this Peer.
66 *
67 * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
68 * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
69 * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
70 * @author <a href="mailto:stephenh@chase3000.com">Stephen Haberman</a>
71 * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
72 * @author <a href="mailto:vido@ldh.org">Augustin Vidovic</a>
73 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
74 * @version $Id: BasePeerImpl.java 1388656 2012-09-21 19:59:16Z tfischer $
75 */
76 public class BasePeerImpl<T> implements Serializable
77 {
78 /**
79 * Serial Version
80 */
81 private static final long serialVersionUID = -7702123730779032381L;
82
83 /** the log */
84 private static final Log log = LogFactory.getLog(BasePeerImpl.class);
85
86 /** An injected instance of a record mapper to map JDBC result sets to objects */
87 private RecordMapper<T> recordMapper = null;
88
89 /** An injected instance of a table map */
90 private TableMap tableMap = null;
91
92 /** An injected instance of the database name */
93 private String databaseName = null;
94
95 /**
96 * Default constructor
97 */
98 public BasePeerImpl()
99 {
100 super();
101 }
102
103 /**
104 * Constructor providing the objects to be injected as parameters.
105 *
106 * @param recordMapper a record mapper to map JDBC result sets to objects
107 * @param tableMap the default table map
108 * @param databaseName the name of the database
109 */
110 public BasePeerImpl(RecordMapper<T> recordMapper, TableMap tableMap, String databaseName)
111 {
112 this();
113 setRecordMapper(recordMapper);
114 setTableMap(tableMap);
115 setDatabaseName(databaseName);
116 }
117
118 /**
119 * Set the record mapper for this instance.
120 *
121 * @param recordMapper the recordMapper to set
122 */
123 public void setRecordMapper(RecordMapper<T> recordMapper)
124 {
125 this.recordMapper = recordMapper;
126 }
127
128 /**
129 * Get the record mapper for this instance.
130 *
131 * @return the recordMapper
132 */
133 public RecordMapper<T> getRecordMapper() throws TorqueException
134 {
135 if (recordMapper == null)
136 {
137 throw new TorqueException("No record mapper injected");
138 }
139
140 return recordMapper;
141 }
142
143 /**
144 * Set the default table map for this instance.
145 *
146 * @param tableMap the tableMap to set
147 */
148 public void setTableMap(TableMap tableMap)
149 {
150 this.tableMap = tableMap;
151 }
152
153 /**
154 * Get the default table map for this instance.
155 *
156 * @return the tableMap
157 */
158 public TableMap getTableMap() throws TorqueException
159 {
160 if (tableMap == null)
161 {
162 throw new TorqueException("No table map injected");
163 }
164
165 return tableMap;
166 }
167
168 /**
169 * Set the database name for this instance.
170 *
171 * @param databaseName the databaseName to set
172 */
173 public void setDatabaseName(String databaseName)
174 {
175 this.databaseName = databaseName;
176 }
177
178 /**
179 * Get the database name for this instance.
180 *
181 * @return the databaseName
182 */
183 public String getDatabaseName() throws TorqueException
184 {
185 if (databaseName == null)
186 {
187 throw new TorqueException("No database name injected");
188 }
189
190 return databaseName;
191 }
192
193 /**
194 * Get the list of objects from a ResultSet.
195 * Please not that the ResultSet MUST return columns in the right order.
196 * You can use getFieldNames() in BaseObject to get the correct sequence.
197 *
198 * @param resultSet the ResultSet to extract the objects from.
199 * @param the database adapter of the database for the result set,
200 * or null if the adapter is unknown.
201 *
202 * @return the list of objects read from the ResultSet.
203 *
204 * @throws TorqueException If the mapping fails.
205 */
206 public List<T> resultSet2Objects(
207 java.sql.ResultSet resultSet,
208 Adapter adapter)
209 throws TorqueException
210 {
211 try
212 {
213 List<T> result = new ArrayList<T>();
214 RecordMapper<T> mapper = getRecordMapper();
215 while (resultSet.next())
216 {
217 result.add(mapper.processRow(resultSet, 0));
218 }
219 return result;
220 }
221 catch (SQLException e)
222 {
223 if (adapter != null)
224 {
225 throw adapter.toTorqueException(e);
226 }
227 throw new TorqueException(e);
228 }
229 }
230
231 /**
232 * Convenience method to create a String array of criteria keys.
233 *
234 * @param tableName Name of table.
235 * @param columnNames A String[].
236 * @return A String[].
237 *
238 * @deprecated This method is not used any more and will be removed in a
239 * future version of Torque.
240 */
241 @Deprecated
242 public String[] initCriteriaKeys(
243 String tableName,
244 String[] columnNames)
245 {
246 String[] keys = new String[columnNames.length];
247 for (int i = 0; i < columnNames.length; i++)
248 {
249 keys[i] = tableName + "." + columnNames[i].toUpperCase();
250 }
251 return keys;
252 }
253
254 /**
255 * Convenience method that uses straight JDBC to delete multiple
256 * rows.
257 *
258 * @param con A Connection.
259 * @param table The table to delete records from.
260 * @param column The column in the where clause.
261 * @param value The value of the column.
262 *
263 * @return the number of deleted rows.
264 *
265 * @throws TorqueException Any exceptions caught during processing will be
266 * rethrown wrapped into a TorqueException.
267 *
268 * @deprecated The value is not SQL escaped.
269 * Better use doDelete(Criteria, String, Connection)
270 * for automatic escaping and more flexibility.
271 * This method will be removed in a future version of Torque.
272 */
273 @Deprecated
274 public int deleteAll(
275 Connection con,
276 String table,
277 String column,
278 int value)
279 throws TorqueException
280 {
281 Statement statement = null;
282 try
283 {
284 statement = con.createStatement();
285
286 StringBuffer query = new StringBuffer();
287 query.append("DELETE FROM ")
288 .append(table)
289 .append(" WHERE ")
290 .append(column)
291 .append(" = ")
292 .append(value);
293
294 return statement.executeUpdate(query.toString());
295 }
296 catch (SQLException e)
297 {
298 throw new TorqueException(e);
299 }
300 finally
301 {
302 if (statement != null)
303 {
304 try
305 {
306 statement.close();
307 }
308 catch (SQLException e)
309 {
310 throw new TorqueException(e);
311 }
312 }
313 }
314 }
315
316 /**
317 * Convenience method that uses straight JDBC to delete multiple
318 * rows. This method attempts to get the default database from
319 * the pool.
320 *
321 * @param table The table to delete records from.
322 * @param column The column in the where clause.
323 * @param value The value of the column.
324 *
325 * @return the number of deleted rows.
326 *
327 * @throws TorqueException Any exceptions caught during processing will be
328 * rethrown wrapped into a TorqueException.
329 *
330 * @deprecated The value is not SQL escaped.
331 * Better use doDelete(Criteria, String)
332 * for automatic escaping and more flexibility.
333 * This method will be removed in a future version of Torque.
334 */
335 @Deprecated
336 public int deleteAll(String table, String column, int value)
337 throws TorqueException
338 {
339 Connection con = null;
340 try
341 {
342 con = Transaction.begin(Torque.getDefaultDB());
343 int result = deleteAll(con, table, column, value);
344 Transaction.commit(con);
345 con = null;
346 return result;
347 }
348 finally
349 {
350 if (con != null)
351 {
352 Transaction.safeRollback(con);
353 }
354 }
355 }
356
357 /**
358 * Deletes rows from a database table.
359 *
360 * @param criteria defines the rows to be deleted, not null.
361 *
362 * @return the number of deleted rows.
363 *
364 * @throws TorqueException Any exceptions caught during processing will be
365 * rethrown wrapped into a TorqueException.
366 */
367 public int doDelete(org.apache.torque.criteria.Criteria criteria)
368 throws TorqueException
369 {
370 Connection connection = null;
371 try
372 {
373 setDbName(criteria);
374 connection = Transaction.begin(criteria.getDbName());
375 int deletedRows = doDelete(criteria, connection);
376 Transaction.commit(connection);
377 connection = null;
378 return deletedRows;
379 }
380 finally
381 {
382 if (connection != null)
383 {
384 Transaction.safeRollback(connection);
385 }
386 }
387 }
388
389 /**
390 * Deletes rows from a table. This method is to be used
391 * during a transaction, otherwise use the doDelete(Criteria) method.
392 *
393 * @param criteria defines the rows to be deleted, not null.
394 * @param connection the connection to use, not null.
395 *
396 * @return the number of deleted rows.
397 *
398 * @throws TorqueException Any exceptions caught during processing will be
399 * rethrown wrapped into a TorqueException.
400 */
401 public int doDelete(
402 org.apache.torque.criteria.Criteria criteria,
403 Connection connection)
404 throws TorqueException
405 {
406 correctBooleans(criteria);
407 setDbName(criteria);
408
409 Query query = SqlBuilder.buildQuery(criteria);
410 query.setType(Query.Type.DELETE);
411
412 String fullTableName;
413 if (tableMap == null)
414 {
415 fullTableName = SqlBuilder.guessFullTableFromCriteria(criteria);
416 }
417 else
418 {
419 fullTableName = SqlBuilder.getFullTableName(
420 tableMap.getName(),
421 criteria.getDbName());
422 }
423 boolean ownTableAdded = false;
424 for (FromElement fromElement : query.getFromClause())
425 {
426 // Table names are case insensitive in known databases
427 // so use case-insensitive compare
428 if (fullTableName.equalsIgnoreCase(fromElement.getFromExpression()))
429 {
430 ownTableAdded = true;
431 break;
432 }
433 }
434 if (!ownTableAdded)
435 {
436 query.getFromClause().add(new FromElement(fullTableName));
437 }
438 String sql = query.toString();
439
440 PreparedStatement preparedStatement = null;
441 try
442 {
443 preparedStatement = connection.prepareStatement(sql);
444 List<Object> replacements = setPreparedStatementReplacements(
445 preparedStatement,
446 query.getPreparedStatementReplacements(),
447 0);
448 long startTime = System.currentTimeMillis();
449 log.debug("Executing delete " + sql
450 + ", parameters = "
451 + replacements);
452
453 int affectedRows = preparedStatement.executeUpdate();
454 long queryEndTime = System.currentTimeMillis();
455 log.trace("delete took " + (queryEndTime - startTime)
456 + " milliseconds");
457
458 preparedStatement.close();
459 preparedStatement = null;
460 return affectedRows;
461 }
462 catch (SQLException e)
463 {
464 final String dbName = criteria.getDbName();
465 final Adapter adapter = Torque.getAdapter(dbName);
466 if (adapter != null)
467 {
468 throw adapter.toTorqueException(e);
469 }
470 throw new TorqueException(e);
471 }
472 finally
473 {
474 if (preparedStatement != null)
475 {
476 try
477 {
478 preparedStatement.close();
479 }
480 catch (SQLException e)
481 {
482 log.warn("error closing prepared statement", e);
483 }
484 }
485 }
486 }
487
488 /**
489 * Method to perform deletes based on conditions in a Criteria.
490 *
491 * @param criteria The criteria to use.
492 *
493 * @return the number of deleted rows.
494 *
495 * @throws TorqueException Any exceptions caught during processing will be
496 * rethrown wrapped into a TorqueException.
497 *
498 * @deprecated This method causes unexpected results when joins are used.
499 * Please use doDelete(
500 * org.apache.torque.criteria.Criteria, TableMap).
501 * This method will be removed in a future version of Torque.
502 */
503 @Deprecated
504 protected int doDelete(Criteria criteria) throws TorqueException
505 {
506 Connection con = null;
507 try
508 {
509 con = Transaction.begin(criteria.getDbName());
510 int result = doDelete(criteria, con);
511 Transaction.commit(con);
512 con = null;
513 return result;
514 }
515 finally
516 {
517 if (con != null)
518 {
519 Transaction.safeRollback(con);
520 }
521 }
522 }
523
524 /**
525 * Method to perform deletes based on conditions a Criteria.
526 *
527 * @param criteria The criteria to use.
528 * @param con the Connection to be used for deleting.
529 *
530 * @return the number of deleted rows.
531 *
532 * @throws TorqueException Any exceptions caught during processing will be
533 * rethrown wrapped into a TorqueException.
534 *
535 * @deprecated This method causes unexpected results when joins are used.
536 * Please use doDelete(
537 * org.apache.torque.criteria.Criteria, TableMap, Connection).
538 * This method will be removed in a future version of Torque.
539 */
540 @Deprecated
541 protected int doDelete(Criteria criteria, Connection con)
542 throws TorqueException
543 {
544 if (criteria.values().isEmpty())
545 {
546 throw new TorqueException("No conditions found in Criteria");
547 }
548 Criteria.Criterion criterion
549 = criteria.values().iterator().next();
550
551 TableMap tableMapFromCriteria = MapHelper.getTableMap(
552 criterion.getColumn(), criteria, null);
553 if (tableMapFromCriteria == null)
554 {
555 throw new TorqueException("Unqualified column name in criteria"
556 + " or table name not found in database map");
557 }
558
559 Query query = SqlBuilder.buildQuery(criteria);
560 query.setType(Query.Type.DELETE);
561
562 String fullTableName = null;
563 if (tableMap != null)
564 {
565 fullTableName = SqlBuilder.getFullTableName(
566 tableMap.getName(),
567 criteria.getDbName());
568 }
569 else
570 {
571 Column column = criteria.values().iterator().next().getColumn();
572 fullTableName = SqlBuilder.getFullTableName(
573 column.getFullTableName(),
574 criteria.getDbName());
575 }
576
577 boolean ownTableAdded = false;
578 for (FromElement fromElement : query.getFromClause())
579 {
580 // Table names are case insensitive in known databases
581 // so use case-insensitive compare
582 if (fullTableName.equalsIgnoreCase(fromElement.getFromExpression()))
583 {
584 ownTableAdded = true;
585 break;
586 }
587 }
588 if (!ownTableAdded)
589 {
590 query.getFromClause().add(new FromElement(fullTableName));
591 }
592 String sql = query.toString();
593
594 PreparedStatement preparedStatement = null;
595 try
596 {
597 preparedStatement = con.prepareStatement(sql);
598 List<Object> replacements = setPreparedStatementReplacements(
599 preparedStatement,
600 query.getPreparedStatementReplacements(),
601 0);
602 long startTime = System.currentTimeMillis();
603 log.debug("Executing delete " + sql
604 + ", parameters = "
605 + replacements);
606
607 int affectedRows = preparedStatement.executeUpdate();
608 long queryEndTime = System.currentTimeMillis();
609 log.trace("delete took " + (queryEndTime - startTime)
610 + " milliseconds");
611
612 preparedStatement.close();
613 preparedStatement = null;
614 return affectedRows;
615 }
616 catch (SQLException e)
617 {
618 final String dbName = criteria.getDbName();
619 final Adapter adapter = Torque.getAdapter(dbName);
620 if (adapter != null)
621 {
622 throw adapter.toTorqueException(e);
623 }
624 throw new TorqueException(e);
625 }
626 finally
627 {
628 if (preparedStatement != null)
629 {
630 try
631 {
632 preparedStatement.close();
633 }
634 catch (SQLException e)
635 {
636 log.warn("error closing prepared statement", e);
637 }
638 }
639 }
640 }
641
642 /**
643 * Inserts a record into a database table.
644 * <p>
645 * If the primary key is included in Criteria, then that value will
646 * be used to insert the row.
647 * <p>
648 * Otherwise, if the primary key can be generated automatically,
649 * the generated key will be used for the insert and will be returned.
650 * <p>
651 * If no value is given for the primary key is defined and it cannot
652 * be generated automatically or the table has no primary key,
653 * the values will be inserted as specified and null will be returned.
654 *
655 * @param insertValues Contains the values to insert, not null.
656 *
657 * @return the primary key of the inserted row (if the table
658 * has a primary key) or null (if the table does not have
659 * a primary key).
660 *
661 * @throws TorqueException if a database error occurs.
662 */
663 public ObjectKey doInsert(ColumnValues insertValues)
664 throws TorqueException
665 {
666 String databaseNameFromInsertValues = insertValues.getDbName();
667 if (databaseNameFromInsertValues == null)
668 {
669 databaseNameFromInsertValues = getDatabaseName();
670 }
671 Connection connection = null;
672 try
673 {
674 connection = Transaction.begin(databaseNameFromInsertValues);
675 ObjectKey id = doInsert(insertValues, connection);
676 Transaction.commit(connection);
677 connection = null;
678 return id;
679 }
680 finally
681 {
682 if (connection != null)
683 {
684 Transaction.safeRollback(connection);
685 }
686 }
687 }
688
689 /**
690 * Inserts a record into a database table.
691 * <p>
692 * If the primary key is included in Criteria, then that value will
693 * be used to insert the row.
694 * <p>
695 * Otherwise, if the primary key can be generated automatically,
696 * the generated key will be used for the insert and will be returned.
697 * <p>
698 * If no value is given for the primary key is defined and it cannot
699 * be generated automatically or the table has no primary key,
700 * the values will be inserted as specified and null will be returned.
701 *
702 * @param insertValues Contains the values to insert, not null.
703 * @param connection the connection to use for the insert, not null.
704 *
705 * @return the primary key of the inserted row (if the table
706 * has a primary key) or null (if the table does not have
707 * a primary key).
708 *
709 * @throws TorqueException if a database error occurs.
710 */
711 public ObjectKey doInsert(
712 ColumnValues insertValues,
713 Connection connection)
714 throws TorqueException
715 {
716 if (insertValues == null)
717 {
718 throw new TorqueException("insertValues is null");
719 }
720 if (connection == null)
721 {
722 throw new TorqueException("connection is null");
723 }
724 String databaseNameFromInsertValues = insertValues.getDbName();
725 if (databaseNameFromInsertValues == null)
726 {
727 databaseNameFromInsertValues = getDatabaseName();
728 }
729 Database database = Torque.getDatabase(databaseNameFromInsertValues);
730 Object keyInfo = getIdMethodInfo();
731 IdGenerator keyGen = database.getIdGenerator(
732 getTableMap().getPrimaryKeyMethod());
733
734 SimpleKey id = null;
735 // can currently generate only single column pks, therefore a single
736 // columnMap is ok
737 ColumnMap primaryKey = null;
738 if (keyGen != null)
739 {
740 // fail on multiple pks
741 primaryKey = getTableMap().getPrimaryKey();
742
743 // primaryKey will be null if there is no primary key
744 // defined for the table we're inserting into.
745 if (keyGen.isPriorToInsert() && primaryKey != null
746 && !insertValues.containsKey(
747 primaryKey))
748 {
749 id = getId(primaryKey, keyGen, connection, keyInfo);
750 insertValues.put(
751 primaryKey,
752 new JdbcTypedValue(id.getValue(), id.getJdbcType()));
753 }
754 }
755
756 List<String> columnNames = new ArrayList<String>();
757 List<JdbcTypedValue> replacementObjects
758 = new ArrayList<JdbcTypedValue>();
759 for (Map.Entry<Column, JdbcTypedValue> columnValue
760 : insertValues.entrySet())
761 {
762 Column column = columnValue.getKey();
763 columnNames.add(column.getColumnName());
764 JdbcTypedValue value = columnValue.getValue();
765 replacementObjects.add(value);
766 }
767
768 String fullTableName = SqlBuilder.getFullTableName(
769 getTableMap().getName(),
770 databaseNameFromInsertValues);
771 StringBuilder query = new StringBuilder("INSERT INTO ")
772 .append(fullTableName)
773 .append("(")
774 .append(StringUtils.join(columnNames, ","))
775 .append(") VALUES (");
776 for (int i = 0; i < columnNames.size(); ++i)
777 {
778 if (i != 0)
779 {
780 query.append(",");
781 }
782 query.append("?");
783 }
784 query.append(")");
785
786 PreparedStatement preparedStatement = null;
787 try
788 {
789 preparedStatement = connection.prepareStatement(query.toString());
790 int position = 1;
791 for (JdbcTypedValue replacementObject : replacementObjects)
792 {
793 Object value = replacementObject.getValue();
794 if (value != null)
795 {
796 if (replacementObject.getJdbcType() != Types.BLOB
797 && replacementObject.getJdbcType() != Types.CLOB)
798 {
799 preparedStatement.setObject(
800 position,
801 value,
802 replacementObject.getJdbcType());
803 }
804 else
805 {
806 preparedStatement.setObject(
807 position,
808 value);
809 }
810 }
811 else
812 {
813 preparedStatement.setNull(
814 position,
815 replacementObject.getJdbcType());
816 }
817 position++;
818 }
819 long startTime = System.currentTimeMillis();
820 log.debug("Executing insert " + query.toString()
821 + " using parameters " + replacementObjects);
822
823 preparedStatement.executeUpdate();
824 long queryEndTime = System.currentTimeMillis();
825 log.trace("insert took " + (queryEndTime - startTime)
826 + " milliseconds");
827
828 preparedStatement.close();
829 preparedStatement = null;
830 }
831 catch (SQLException e)
832 {
833 final String dbName = insertValues.getDbName();
834 final Adapter adapter = Torque.getAdapter(dbName);
835 if (adapter != null)
836 {
837 throw adapter.toTorqueException(e);
838 }
839 throw new TorqueException(e);
840 }
841 finally
842 {
843 if (preparedStatement != null)
844 {
845 try
846 {
847 preparedStatement.close();
848 }
849 catch (SQLException e)
850 {
851 log.warn("error closing prepared statement", e);
852 }
853 }
854 }
855
856 // If the primary key column is auto-incremented, get the id
857 // now.
858 if (keyGen != null && keyGen.isPostInsert()
859 && primaryKey != null
860 && !insertValues.containsKey(
861 primaryKey))
862 {
863 id = getId(primaryKey, keyGen, connection, keyInfo);
864 }
865
866 return id;
867 }
868
869 /**
870 * Returns the idMethodInfo for the table for this Peer class.
871 *
872 * @return the idMethodInfo, not null.
873 *
874 * @throws TorqueException if the database adapter for the table's database
875 * needs to be accessed but is not configured.
876 */
877 private Object getIdMethodInfo()
878 throws TorqueException
879 {
880 IDMethod idMethod = tableMap.getPrimaryKeyMethod();
881 if (IDMethod.NATIVE == idMethod)
882 {
883 Adapter adapter = Torque.getAdapter(getDatabaseName());
884 if (adapter == null)
885 {
886 throw new TorqueException(
887 "missing adapter configuration for database "
888 + getDatabaseName()
889 + "check the Torque configuration");
890 }
891 idMethod = adapter.getIDMethodType();
892 }
893 Object keyInfo = tableMap.getPrimaryKeyMethodInfo(idMethod);
894 return keyInfo;
895 }
896
897 /**
898 * Create an Id for insertion in the Criteria
899 *
900 * @param pk ColumnMap for the Primary key
901 * @param keyGen The Id Generator object
902 * @param con The SQL Connection to run the id generation under
903 * @param keyInfo KeyInfo Parameter from the Table map
904 *
905 * @return A simple Key representing the new Id value
906 * @throws TorqueException Possible errors get wrapped in here.
907 */
908 private SimpleKey getId(
909 ColumnMap pk,
910 IdGenerator keyGen,
911 Connection con,
912 Object keyInfo)
913 throws TorqueException
914 {
915 SimpleKey id = null;
916
917 if (pk != null && keyGen != null)
918 {
919 if (pk.getType() instanceof Number)
920 {
921 id = new NumberKey(
922 keyGen.getIdAsBigDecimal(con, keyInfo));
923 }
924 else
925 {
926 id = new StringKey(keyGen.getIdAsString(con, keyInfo));
927 }
928 }
929
930 return id;
931 }
932
933 /**
934 * Add all the columns needed to create a new object.
935 *
936 * @param criteria the Criteria to which the select columns should
937 * be added.
938 */
939 public void addSelectColumns(org.apache.torque.criteria.Criteria criteria)
940 {
941 ColumnMap[] columns = this.tableMap.getColumns();
942
943 for (ColumnMap c : columns)
944 {
945 criteria.addSelectColumn(c);
946 }
947 }
948
949 /**
950 * Add all the columns needed to create a new object.
951 *
952 * @param criteria the Criteria to which the select columns should
953 * be added.
954 *
955 * @deprecated Please use addSelectColumns(
956 * org.apache.torque.criteria.Criteria).
957 * This method will be removed in a future version of Torque.
958 */
959 @Deprecated
960 public void addSelectColumns(Criteria criteria)
961 {
962 ColumnMap[] columns = this.tableMap.getColumns();
963
964 for (ColumnMap c : columns)
965 {
966 criteria.addSelectColumn(c);
967 }
968 }
969
970 /**
971 * Selects objects from a database.
972 *
973 * @param criteria object used to create the SELECT statement.
974 *
975 * @return the list of selected objects, not null.
976 *
977 * @throws TorqueException Any exceptions caught during processing will be
978 * rethrown wrapped into a TorqueException.
979 *
980 * @deprecated Please use doSelect(org.apache.torque.criteria.Criteria).
981 * This method will be removed in a future version of Torque.
982 */
983 @Deprecated
984 public List<T> doSelect(Criteria criteria)
985 throws TorqueException
986 {
987 if (criteria.getSelectColumns().size() == 0)
988 {
989 addSelectColumns(criteria);
990 }
991 setDbName(criteria);
992
993 return doSelect(
994 criteria,
995 getRecordMapper());
996 }
997
998 /**
999 * Selects objects from a database.
1000 *
1001 * @param criteria object used to create the SELECT statement.
1002 *
1003 * @return the list of selected objects, not null.
1004 *
1005 * @throws TorqueException Any exceptions caught during processing will be
1006 * rethrown wrapped into a TorqueException.
1007 */
1008 public List<T> doSelect(org.apache.torque.criteria.Criteria criteria)
1009 throws TorqueException
1010 {
1011 if (criteria.getSelectColumns().size() == 0)
1012 {
1013 addSelectColumns(criteria);
1014 }
1015 setDbName(criteria);
1016
1017 return doSelect(
1018 criteria,
1019 getRecordMapper());
1020 }
1021
1022 /**
1023 * Selects objects from a database
1024 * within a transaction.
1025 *
1026 * @param criteria object used to create the SELECT statement.
1027 * @param connection the connection to use, not null.
1028 *
1029 * @return the list of selected objects, not null.
1030 *
1031 * @throws TorqueException Any exceptions caught during processing will be
1032 * rethrown wrapped into a TorqueException.
1033 *
1034 * @deprecated Please use doSelect(org.apache.torque.criteria.Criteria,
1035 * Connection).
1036 * This method will be removed in a future version of Torque.
1037 */
1038 @Deprecated
1039 public List<T> doSelect(
1040 Criteria criteria,
1041 Connection connection)
1042 throws TorqueException
1043 {
1044 if (criteria.getSelectColumns().size() == 0)
1045 {
1046 addSelectColumns(criteria);
1047 }
1048 setDbName(criteria);
1049
1050 return doSelect(
1051 criteria,
1052 getRecordMapper(),
1053 connection);
1054 }
1055
1056 /**
1057 * Selects objects from a database
1058 * within a transaction.
1059 *
1060 * @param criteria object used to create the SELECT statement.
1061 * @param connection the connection to use, not null.
1062 *
1063 * @return the list of selected objects, not null.
1064 *
1065 * @throws TorqueException Any exceptions caught during processing will be
1066 * rethrown wrapped into a TorqueException.
1067 */
1068 public List<T> doSelect(
1069 org.apache.torque.criteria.Criteria criteria,
1070 Connection connection)
1071 throws TorqueException
1072 {
1073 if (criteria.getSelectColumns().size() == 0)
1074 {
1075 addSelectColumns(criteria);
1076 }
1077 setDbName(criteria);
1078
1079 return doSelect(
1080 criteria,
1081 getRecordMapper(),
1082 connection);
1083 }
1084
1085 /**
1086 * Selects at most one object from a database.
1087 *
1088 * @param criteria object used to create the SELECT statement.
1089 *
1090 * @return the selected Object, or null if no object was selected.
1091 *
1092 * @throws TorqueException If more than one record is selected or if
1093 * an error occurs when processing the query.
1094 */
1095 public T doSelectSingleRecord(org.apache.torque.criteria.Criteria criteria)
1096 throws TorqueException
1097 {
1098 List<T> recordList = doSelect(criteria);
1099 T record = null;
1100 if (recordList.size() > 1)
1101 {
1102 throw new TooManyRowsException("Criteria " + criteria
1103 + " matched more than one record");
1104 }
1105 if (!recordList.isEmpty())
1106 {
1107 record = recordList.get(0);
1108 }
1109 return record;
1110 }
1111
1112 /**
1113 * Selects at most one object from a database
1114 * within a transaction.
1115 *
1116 * @param criteria object used to create the SELECT statement.
1117 * @param connection the connection holding the transaction, not null.
1118 *
1119 * @return the selected Object, or null if no object was selected.
1120 *
1121 * @throws TorqueException If more than one record is selected or if
1122 * an error occurs when processing the query.
1123 */
1124 public T doSelectSingleRecord(
1125 org.apache.torque.criteria.Criteria criteria,
1126 Connection connection)
1127 throws TorqueException
1128 {
1129 List<T> recordList = doSelect(criteria, connection);
1130 T record = null;
1131 if (recordList.size() > 1)
1132 {
1133 throw new TooManyRowsException("Criteria " + criteria
1134 + " matched more than one record");
1135 }
1136 if (!recordList.isEmpty())
1137 {
1138 record = recordList.get(0);
1139 }
1140 return record;
1141 }
1142
1143 /**
1144 * Selects rows from a database an maps them to objects.
1145 *
1146 * @param criteria A Criteria specifying the records to select, not null.
1147 * @param mapper The mapper creating the objects from the resultSet,
1148 * not null.
1149 *
1150 * @return The results of the query, not null.
1151 *
1152 * @throws TorqueException if querying the database fails.
1153 *
1154 * @deprecated Please use doSelect(org.apache.torque.criteria.Criteria,
1155 * RecordMapper).
1156 * This method will be removed in a future version of Torque.
1157 */
1158 @Deprecated
1159 public <TT> List<TT> doSelect(
1160 Criteria criteria,
1161 RecordMapper<TT> mapper)
1162 throws TorqueException
1163 {
1164 Connection connection = null;
1165 try
1166 {
1167 connection = Transaction.begin(criteria.getDbName());
1168
1169 List<TT> result = doSelect(
1170 criteria,
1171 mapper,
1172 connection);
1173
1174 Transaction.commit(connection);
1175 connection = null;
1176 return result;
1177 }
1178 finally
1179 {
1180 if (connection != null)
1181 {
1182 Transaction.safeRollback(connection);
1183 }
1184 }
1185 }
1186
1187 /**
1188 * Selects rows from a database an maps them to objects.
1189 *
1190 * @param criteria A Criteria specifying the records to select, not null.
1191 * @param mapper The mapper creating the objects from the resultSet,
1192 * not null.
1193 *
1194 * @return The results of the query, not null.
1195 *
1196 * @throws TorqueException if querying the database fails.
1197 */
1198 public <TT> List<TT> doSelect(
1199 org.apache.torque.criteria.Criteria criteria,
1200 RecordMapper<TT> mapper)
1201 throws TorqueException
1202 {
1203 Connection connection = null;
1204 try
1205 {
1206 connection = Transaction.begin(criteria.getDbName());
1207
1208 List<TT> result = doSelect(
1209 criteria,
1210 mapper,
1211 connection);
1212
1213 Transaction.commit(connection);
1214 connection = null;
1215 return result;
1216 }
1217 finally
1218 {
1219 if (connection != null)
1220 {
1221 Transaction.safeRollback(connection);
1222 }
1223 }
1224 }
1225
1226 /**
1227 * Selects rows from a database an maps them to objects.
1228 *
1229 * @param query the sql query to execute, not null.
1230 *
1231 * @return The results of the query, not null.
1232 *
1233 * @throws TorqueException if querying the database fails.
1234 */
1235 public List<T> doSelect(String query)
1236 throws TorqueException
1237 {
1238 return doSelect(
1239 query,
1240 getRecordMapper(),
1241 getDatabaseName());
1242 }
1243
1244 /**
1245 * Selects rows from a database an maps them to objects.
1246 *
1247 * @param query the SQL Query to execute, not null.
1248 * @param dbName The name of the database to select from,
1249 * or null for the default DB.
1250 * @param connection the database connection, not null.
1251 *
1252 * @return The results of the query, not null.
1253 *
1254 * @throws TorqueException if querying the database fails.
1255 */
1256 public List<T> doSelect(
1257 String query,
1258 String dbName,
1259 Connection connection)
1260 throws TorqueException
1261 {
1262 return doSelect(
1263 query,
1264 getRecordMapper(),
1265 dbName,
1266 connection);
1267 }
1268
1269 /**
1270 * Selects rows from a database an maps them to objects.
1271 *
1272 * @param query the sql query to execute, not null.
1273 * @param mapper The mapper creating the objects from the resultSet,
1274 * not null.
1275 * @param dbName The name of the database to create the connection for,
1276 * or null for the default DB.
1277 *
1278 * @return The results of the query, not null.
1279 *
1280 * @throws TorqueException if querying the database fails.
1281 */
1282 public <TT> List<TT> doSelect(
1283 String query,
1284 RecordMapper<TT> mapper,
1285 String dbName)
1286 throws TorqueException
1287 {
1288 Connection connection = null;
1289
1290 try
1291 {
1292 connection = Transaction.begin((dbName == null)
1293 ? Torque.getDefaultDB()
1294 : dbName);
1295
1296 List<TT> result = doSelect(
1297 query,
1298 mapper,
1299 dbName,
1300 connection);
1301
1302 Transaction.commit(connection);
1303 connection = null;
1304 return result;
1305 }
1306 finally
1307 {
1308 if (connection != null)
1309 {
1310 Transaction.safeRollback(connection);
1311 }
1312 }
1313 }
1314
1315 /**
1316 * Selects rows from a database an maps them to objects.
1317 *
1318 * @param query the SQL Query to execute, not null.
1319 * @param mapper The mapper creating the objects from the resultSet,
1320 * not null.
1321 * @param dbName The name of the database to create the connection for,
1322 * or null for the default DB.
1323 * @param connection the database connection, not null.
1324 *
1325 * @return The results of the query, not null.
1326 *
1327 * @throws TorqueException if querying the database fails.
1328 */
1329 public <TT> List<TT> doSelect(
1330 String query,
1331 RecordMapper<TT> mapper,
1332 String dbName,
1333 Connection connection)
1334 throws TorqueException
1335 {
1336 if (connection == null)
1337 {
1338 throw new NullPointerException("connection is null");
1339 }
1340
1341 List<TT> result = new ArrayList<TT>();
1342 Statement statement = null;
1343 ResultSet resultSet = null;
1344 try
1345 {
1346 statement = connection.createStatement();
1347 long startTime = System.currentTimeMillis();
1348 log.debug("Executing query " + query);
1349
1350 resultSet = statement.executeQuery(query.toString());
1351 long queryEndTime = System.currentTimeMillis();
1352 log.trace("query took " + (queryEndTime - startTime)
1353 + " milliseconds");
1354
1355 while (resultSet.next())
1356 {
1357 TT rowResult = mapper.processRow(resultSet, 0);
1358 result.add(rowResult);
1359 }
1360 long mappingEndTime = System.currentTimeMillis();
1361 log.trace("mapping took " + (mappingEndTime - queryEndTime)
1362 + " milliseconds");
1363 }
1364 catch (SQLException e)
1365 {
1366 final Adapter adapter = Torque.getAdapter(dbName);
1367 if (adapter != null)
1368 {
1369 throw adapter.toTorqueException(e);
1370 }
1371 throw new TorqueException(e);
1372 }
1373 finally
1374 {
1375 if (resultSet != null)
1376 {
1377 try
1378 {
1379 resultSet.close();
1380 }
1381 catch (SQLException e)
1382 {
1383 log.warn("error closing resultSet", e);
1384 }
1385 }
1386 if (statement != null)
1387 {
1388 try
1389 {
1390 statement.close();
1391 }
1392 catch (SQLException e)
1393 {
1394 log.warn("error closing statement", e);
1395 }
1396 }
1397 }
1398 return result;
1399 }
1400
1401 /**
1402 * Performs a SQL <code>select</code> using a PreparedStatement.
1403 *
1404 * @param criteria A Criteria specifying the records to select, not null.
1405 * @param mapper The mapper creating the objects from the resultSet,
1406 * not null.
1407 * @param connection the database connection for selecting records,
1408 * not null.
1409 *
1410 * @return The results of the query, not null.
1411 *
1412 * @throws TorqueException Error performing database query.
1413 *
1414 * @deprecated Please use doSelect(org.apache.torque.criteria.Criteria,
1415 * RecordMapper, Connection).
1416 * This method will be removed in a future version of Torque.
1417 */
1418 @Deprecated
1419 public <TT> List<TT> doSelect(
1420 Criteria criteria,
1421 RecordMapper<TT> mapper,
1422 Connection connection)
1423 throws TorqueException
1424 {
1425 correctBooleans(criteria);
1426
1427 Query query = SqlBuilder.buildQuery(criteria);
1428 if (query.getFromClause().isEmpty())
1429 {
1430 String tableName = SqlBuilder.getFullTableName(
1431 getTableMap().getName(),
1432 criteria.getDbName());
1433 query.getFromClause().add(new FromElement(tableName));
1434 }
1435
1436 PreparedStatement statement = null;
1437 ResultSet resultSet = null;
1438 try
1439 {
1440 statement = connection.prepareStatement(query.toString());
1441
1442 List<Object> replacements = setPreparedStatementReplacements(
1443 statement,
1444 query.getPreparedStatementReplacements(),
1445 0);
1446
1447 long startTime = System.currentTimeMillis();
1448 log.debug("Executing query " + query
1449 + ", parameters = "
1450 + replacements);
1451
1452 resultSet = statement.executeQuery();
1453 long queryEndTime = System.currentTimeMillis();
1454 log.trace("query took " + (queryEndTime - startTime)
1455 + " milliseconds");
1456
1457 long offset;
1458 Database database = Torque.getDatabase(criteria.getDbName());
1459 if (database.getAdapter().supportsNativeOffset())
1460 {
1461 offset = 0; //database takes care of offset
1462 }
1463 else
1464 {
1465 offset = criteria.getOffset();
1466 }
1467
1468 long limit;
1469 if (database.getAdapter().supportsNativeLimit())
1470 {
1471 limit = -1; //database takes care of offset
1472 }
1473 else
1474 {
1475 if (database.getAdapter().supportsNativeOffset())
1476 {
1477 limit = criteria.getLimit();
1478 }
1479 else
1480 {
1481 if (criteria.getLimit() == -1)
1482 {
1483 limit = criteria.getLimit();
1484 }
1485 else
1486 {
1487 limit = offset + criteria.getLimit();
1488 }
1489 }
1490 }
1491
1492 List<TT> result = new ArrayList<TT>();
1493 int rowNumber = 0;
1494 while (resultSet.next())
1495 {
1496 if (rowNumber < offset)
1497 {
1498 rowNumber++;
1499 continue;
1500 }
1501 if (limit >= 0 && rowNumber >= limit)
1502 {
1503 break;
1504 }
1505
1506 TT rowResult = mapper.processRow(resultSet, 0);
1507 result.add(rowResult);
1508
1509 rowNumber++;
1510 }
1511 long mappingEndTime = System.currentTimeMillis();
1512 log.trace("mapping took " + (mappingEndTime - queryEndTime)
1513 + " milliseconds");
1514
1515 if (criteria.isSingleRecord() && result.size() > 1)
1516 {
1517 throw new TooManyRowsException(
1518 "Criteria expected single Record and "
1519 + "Multiple Records were selected");
1520 }
1521 return result;
1522 }
1523 catch (SQLException e)
1524 {
1525 String dbName = criteria.getDbName();
1526 final Adapter adapter = Torque.getAdapter(dbName);
1527 if (adapter != null)
1528 {
1529 throw adapter.toTorqueException(e);
1530 }
1531 throw new TorqueException(e);
1532 }
1533 finally
1534 {
1535 if (resultSet != null)
1536 {
1537 try
1538 {
1539 resultSet.close();
1540 }
1541 catch (SQLException e)
1542 {
1543 log.warn("error closing resultSet", e);
1544 }
1545 }
1546 if (statement != null)
1547 {
1548 try
1549 {
1550 statement.close();
1551 }
1552 catch (SQLException e)
1553 {
1554 log.warn("error closing statement", e);
1555 }
1556 }
1557 }
1558 }
1559
1560 /**
1561 * Performs a SQL <code>select</code> using a PreparedStatement.
1562 *
1563 * @param criteria A Criteria specifying the records to select, not null.
1564 * @param mapper The mapper creating the objects from the resultSet,
1565 * not null.
1566 * @param connection the database connection for selecting records,
1567 * not null.
1568 *
1569 * @return The results of the query, not null.
1570 *
1571 * @throws TorqueException Error performing database query.
1572 */
1573 public <TT> List<TT> doSelect(
1574 org.apache.torque.criteria.Criteria criteria,
1575 RecordMapper<TT> mapper,
1576 Connection connection)
1577 throws TorqueException
1578 {
1579 correctBooleans(criteria);
1580
1581 Query query = SqlBuilder.buildQuery(criteria);
1582 if (query.getFromClause().isEmpty())
1583 {
1584 String tableName = SqlBuilder.getFullTableName(
1585 getTableMap().getName(),
1586 criteria.getDbName());
1587 query.getFromClause().add(new FromElement(tableName));
1588 }
1589
1590 PreparedStatement statement = null;
1591 ResultSet resultSet = null;
1592 try
1593 {
1594 statement = connection.prepareStatement(query.toString());
1595 if (query.getFetchSize() != null)
1596 {
1597 statement.setFetchSize(query.getFetchSize());
1598 }
1599
1600 List<Object> replacements = setPreparedStatementReplacements(
1601 statement,
1602 query.getPreparedStatementReplacements(),
1603 0);
1604
1605 long startTime = System.currentTimeMillis();
1606 log.debug("Executing query " + query
1607 + ", parameters = "
1608 + replacements);
1609
1610 resultSet = statement.executeQuery();
1611 long queryEndTime = System.currentTimeMillis();
1612 log.trace("query took " + (queryEndTime - startTime)
1613 + " milliseconds");
1614
1615 long offset;
1616 Database database = Torque.getDatabase(criteria.getDbName());
1617 if (database.getAdapter().supportsNativeOffset())
1618 {
1619 offset = 0; //database takes care of offset
1620 }
1621 else
1622 {
1623 offset = criteria.getOffset();
1624 }
1625
1626 long limit;
1627 if (database.getAdapter().supportsNativeLimit())
1628 {
1629 limit = -1; //database takes care of offset
1630 }
1631 else
1632 {
1633 if (database.getAdapter().supportsNativeOffset())
1634 {
1635 limit = criteria.getLimit();
1636 }
1637 else
1638 {
1639 if (criteria.getLimit() == -1)
1640 {
1641 limit = criteria.getLimit();
1642 }
1643 else
1644 {
1645 limit = offset + criteria.getLimit();
1646 }
1647 }
1648 }
1649
1650 List<TT> result = new ArrayList<TT>();
1651 int rowNumber = 0;
1652 while (resultSet.next())
1653 {
1654 if (rowNumber < offset)
1655 {
1656 rowNumber++;
1657 continue;
1658 }
1659 if (limit >= 0 && rowNumber >= limit)
1660 {
1661 break;
1662 }
1663
1664 TT rowResult = mapper.processRow(resultSet, 0);
1665 result.add(rowResult);
1666
1667 rowNumber++;
1668 }
1669 long mappingEndTime = System.currentTimeMillis();
1670 log.trace("mapping took " + (mappingEndTime - queryEndTime)
1671 + " milliseconds");
1672
1673 if (criteria.isSingleRecord() && result.size() > 1)
1674 {
1675 throw new TooManyRowsException(
1676 "Criteria expected single Record and "
1677 + "Multiple Records were selected");
1678 }
1679 return result;
1680 }
1681 catch (SQLException e)
1682 {
1683 String dbName = criteria.getDbName();
1684 final Adapter adapter = Torque.getAdapter(dbName);
1685 if (adapter != null)
1686 {
1687 throw adapter.toTorqueException(e);
1688 }
1689 throw new TorqueException(e);
1690 }
1691 finally
1692 {
1693 if (resultSet != null)
1694 {
1695 try
1696 {
1697 resultSet.close();
1698 }
1699 catch (SQLException e)
1700 {
1701 log.warn("error closing resultSet", e);
1702 }
1703 }
1704 if (statement != null)
1705 {
1706 try
1707 {
1708 statement.close();
1709 }
1710 catch (SQLException e)
1711 {
1712 log.warn("error closing statement", e);
1713 }
1714 }
1715 }
1716 }
1717
1718 /**
1719 * Selects at most a single row from a database an maps them to objects.
1720 *
1721 * @param criteria A Criteria specifying the records to select, not null.
1722 * @param mapper The mapper creating the objects from the resultSet,
1723 * not null.
1724 *
1725 * @return The selected row, or null if no records was selected.
1726 *
1727 * @throws TorqueException if querying the database fails.
1728 */
1729 public <TT> TT doSelectSingleRecord(
1730 org.apache.torque.criteria.Criteria criteria,
1731 RecordMapper<TT> mapper)
1732 throws TorqueException
1733 {
1734 List<TT> resultList = doSelect(criteria, mapper);
1735 TT result = null;
1736 if (resultList.size() > 1)
1737 {
1738 throw new TooManyRowsException("Criteria " + criteria
1739 + " matched more than one record");
1740 }
1741 if (!resultList.isEmpty())
1742 {
1743 result = resultList.get(0);
1744 }
1745 return result;
1746 }
1747
1748 /**
1749 * Selects at most a single row from a database an maps them to objects.
1750 *
1751 * @param criteria A Criteria specifying the records to select, not null.
1752 * @param mapper The mapper creating the objects from the resultSet,
1753 * not null.
1754 * @param connection the database connection, not null.
1755 *
1756 * @return The selected row, or null if no records was selected.
1757 *
1758 * @throws TorqueException if querying the database fails.
1759 */
1760 public <TT> TT doSelectSingleRecord(
1761 org.apache.torque.criteria.Criteria criteria,
1762 RecordMapper<TT> mapper,
1763 Connection connection)
1764 throws TorqueException
1765 {
1766 List<TT> resultList = doSelect(
1767 criteria,
1768 mapper,
1769 connection);
1770 TT result = null;
1771 if (resultList.size() > 1)
1772 {
1773 throw new TooManyRowsException("Criteria " + criteria
1774 + " matched more than one record");
1775 }
1776 if (!resultList.isEmpty())
1777 {
1778 result = resultList.get(0);
1779 }
1780 return result;
1781 }
1782
1783 /**
1784 * Convenience method used to update rows in the DB. Checks if a
1785 * <i>single</i> primary key is specified in the Criteria
1786 * object and uses it to perform the update. If no primary key is
1787 * specified or the table has multiple primary keys,
1788 * an Exception will be thrown.
1789 * <p>
1790 * Use this method for performing an update of the kind:
1791 * <p>
1792 * "WHERE primary_key_id = someValue"
1793 * <p>
1794 * To perform an update on a table with multiple primary keys or
1795 * an update with non-primary key fields in the WHERE
1796 * clause, use doUpdate(ColumnValues, Criteria).
1797 *
1798 * @param updateValues Which columns to update with which values
1799 * for which primary key value, not null.
1800 *
1801 * @return the number of affected rows.
1802 *
1803 * @throws TorqueException Any exceptions caught during processing will be
1804 * rethrown wrapped into a TorqueException.
1805 */
1806 public int doUpdate(ColumnValues updateValues)
1807 throws TorqueException
1808 {
1809 String databaseNameFromUpdateValues = updateValues.getDbName();
1810 if (databaseNameFromUpdateValues == null)
1811 {
1812 databaseNameFromUpdateValues = getDatabaseName();
1813 }
1814 Connection connection = null;
1815 try
1816 {
1817 connection = Transaction.begin(databaseNameFromUpdateValues);
1818 int result = doUpdate(updateValues, connection);
1819 Transaction.commit(connection);
1820 connection = null;
1821 return result;
1822 }
1823 finally
1824 {
1825 if (connection != null)
1826 {
1827 Transaction.safeRollback(connection);
1828 }
1829 }
1830 }
1831
1832 /**
1833 * Convenience method used to update rows in the DB. Checks if a
1834 * <i>single</i> primary key is specified in the Criteria
1835 * object and uses it to perform the update. If no primary key is
1836 * specified or the table has multiple primary keys,
1837 * an Exception will be thrown.
1838 * <p>
1839 * Use this method for performing an update of the kind:
1840 * <p>
1841 * "WHERE primary_key_id = someValue"
1842 * <p>
1843 * To perform an update on a table with multiple primary keys or
1844 * an update with non-primary key fields in the WHERE
1845 * clause, use doUpdate(ColumnValues, Criteria, Connection).
1846 *
1847 * @param updateValues Which columns to update with which values
1848 * for which primary key value, not null.
1849 * @param connection the database connection to use.
1850 *
1851 * @return the number of affected rows.
1852 *
1853 * @throws TorqueException Any exceptions caught during processing will be
1854 * rethrown wrapped into a TorqueException.
1855 */
1856 public int doUpdate(
1857 ColumnValues updateValues,
1858 Connection connection)
1859 throws TorqueException
1860 {
1861 ColumnMap pk = getTableMap().getPrimaryKey();
1862 org.apache.torque.criteria.Criteria selectCriteria = null;
1863
1864 if (pk != null && updateValues.containsKey(pk.getSqlExpression()))
1865 {
1866 selectCriteria = new org.apache.torque.criteria.Criteria();
1867 selectCriteria.where(pk,
1868 updateValues.remove(pk.getSqlExpression()));
1869 }
1870 else
1871 {
1872 throw new TorqueException("No PK specified for database update");
1873 }
1874
1875 return doUpdate(selectCriteria, updateValues, connection);
1876 }
1877
1878 /**
1879 * Executes an update against the database. The rows to be updated
1880 * are selected using <code>criteria</code> and updated using the values
1881 * in <code>updateValues</code>.
1882 *
1883 * @param selectCriteria selects which rows of which table
1884 * should be updated, not null.
1885 * @param updateValues Which columns to update with which values, not null.
1886 *
1887 * @return the number of affected rows.
1888 *
1889 * @throws TorqueException if updating fails.
1890 *
1891 * @deprecated Please use doUpdate(
1892 * org.apache.torque.criteria.Criteria, ColumnValues).
1893 * This method will be removed in a future version of Torque.
1894 */
1895 @Deprecated
1896 public int doUpdate(
1897 Criteria selectCriteria,
1898 ColumnValues updateValues)
1899 throws TorqueException
1900 {
1901 String databaseNameFromUpdateValues = updateValues.getDbName();
1902 if (databaseNameFromUpdateValues == null)
1903 {
1904 databaseNameFromUpdateValues = getDatabaseName();
1905 }
1906 Connection connection = null;
1907 try
1908 {
1909 connection = Transaction.begin(databaseNameFromUpdateValues);
1910 int result = doUpdate(selectCriteria, updateValues, connection);
1911 Transaction.commit(connection);
1912 connection = null;
1913 return result;
1914 }
1915 finally
1916 {
1917 if (connection != null)
1918 {
1919 Transaction.safeRollback(connection);
1920 }
1921 }
1922 }
1923
1924 /**
1925 * Executes an update against the database. The rows to be updated
1926 * are selected using <code>criteria</code> and updated using the values
1927 * in <code>updateValues</code>.
1928 *
1929 * @param selectCriteria selects which rows of which table
1930 * should be updated, not null.
1931 * @param updateValues Which columns to update with which values, not null.
1932 *
1933 * @return the number of affected rows.
1934 *
1935 * @throws TorqueException if updating fails.
1936 */
1937 public int doUpdate(
1938 org.apache.torque.criteria.Criteria selectCriteria,
1939 ColumnValues updateValues)
1940 throws TorqueException
1941 {
1942 String databaseNameFromUpdateValues = updateValues.getDbName();
1943 if (databaseNameFromUpdateValues == null)
1944 {
1945 databaseNameFromUpdateValues = getDatabaseName();
1946 }
1947 Connection connection = null;
1948 try
1949 {
1950 connection = Transaction.begin(databaseNameFromUpdateValues);
1951 int result = doUpdate(selectCriteria, updateValues, connection);
1952 Transaction.commit(connection);
1953 connection = null;
1954 return result;
1955 }
1956 finally
1957 {
1958 if (connection != null)
1959 {
1960 Transaction.safeRollback(connection);
1961 }
1962 }
1963 }
1964
1965 /**
1966 * Executes an update against the database. The rows to be updated
1967 * are selected using <code>criteria</code> and updated using the values
1968 * in <code>updateValues</code>.
1969 *
1970 * @param criteria selects which rows of which table should be updated.
1971 * @param updateValues Which columns to update with which values, not null.
1972 * @param connection the database connection to use, not null.
1973 *
1974 * @return the number of affected rows.
1975 *
1976 * @throws TorqueException if updating fails.
1977 *
1978 * @deprecated Please use doUpdate(org.apache.torque.criteria.Criteria,
1979 * ColumnValues, Connection).
1980 * This method will be removed in a future version of Torque.
1981 */
1982 @Deprecated
1983 public int doUpdate(
1984 Criteria criteria,
1985 ColumnValues updateValues,
1986 Connection connection)
1987 throws TorqueException
1988 {
1989 Query query = SqlBuilder.buildQuery(criteria);
1990 query.setType(Query.Type.UPDATE);
1991
1992 query.getFromClause().clear();
1993 String fullTableName = SqlBuilder.getFullTableName(
1994 getTableMap().getName(),
1995 criteria.getDbName());
1996 query.getFromClause().add(new FromElement(fullTableName));
1997
1998 List<JdbcTypedValue> replacementObjects
1999 = new ArrayList<JdbcTypedValue>();
2000 for (Map.Entry<Column, JdbcTypedValue> updateValue
2001 : updateValues.entrySet())
2002 {
2003 Column column = updateValue.getKey();
2004 query.getSelectClause().add(column.getColumnName());
2005 replacementObjects.add(updateValue.getValue());
2006 }
2007
2008 PreparedStatement preparedStatement = null;
2009 try
2010 {
2011 preparedStatement = connection.prepareStatement(query.toString());
2012 int position = 1;
2013 for (JdbcTypedValue replacementObject : replacementObjects)
2014 {
2015 Object value = replacementObject.getValue();
2016 if (value != null)
2017 {
2018 preparedStatement.setObject(position, value);
2019 }
2020 else
2021 {
2022 preparedStatement.setNull(
2023 position,
2024 replacementObject.getJdbcType());
2025 }
2026 position++;
2027 }
2028 List<Object> replacements = setPreparedStatementReplacements(
2029 preparedStatement,
2030 query.getPreparedStatementReplacements(),
2031 position - 1);
2032 long startTime = System.currentTimeMillis();
2033 log.debug("Executing update " + query.toString()
2034 + " using update parameters " + replacementObjects
2035 + " and query parameters "
2036 + replacements);
2037
2038 int affectedRows = preparedStatement.executeUpdate();
2039 long queryEndTime = System.currentTimeMillis();
2040 log.trace("update took " + (queryEndTime - startTime)
2041 + " milliseconds");
2042
2043 preparedStatement.close();
2044 preparedStatement = null;
2045 return affectedRows;
2046 }
2047 catch (SQLException e)
2048 {
2049 String dbName = updateValues.getDbName();
2050 final Adapter adapter = Torque.getAdapter(dbName);
2051 if (adapter != null)
2052 {
2053 throw adapter.toTorqueException(e);
2054 }
2055 throw new TorqueException(e);
2056 }
2057 finally
2058 {
2059 if (preparedStatement != null)
2060 {
2061 try
2062 {
2063 preparedStatement.close();
2064 }
2065 catch (SQLException e)
2066 {
2067 log.warn("error closing prepared statement", e);
2068 }
2069 }
2070 }
2071 }
2072
2073 /**
2074 * Executes an update against the database. The rows to be updated
2075 * are selected using <code>criteria</code> and updated using the values
2076 * in <code>updateValues</code>.
2077 *
2078 * @param criteria selects which rows of which table should be updated.
2079 * @param updateValues Which columns to update with which values, not null.
2080 * @param connection the database connection to use, not null.
2081 *
2082 * @return the number of affected rows.
2083 *
2084 * @throws TorqueException if updating fails.
2085 */
2086 public int doUpdate(
2087 org.apache.torque.criteria.Criteria criteria,
2088 ColumnValues updateValues,
2089 Connection connection)
2090 throws TorqueException
2091 {
2092 Query query = SqlBuilder.buildQuery(criteria);
2093 query.setType(Query.Type.UPDATE);
2094
2095 query.getFromClause().clear();
2096 String fullTableName = SqlBuilder.getFullTableName(
2097 getTableMap().getName(),
2098 criteria.getDbName());
2099 query.getFromClause().add(new FromElement(fullTableName));
2100
2101 List<JdbcTypedValue> replacementObjects
2102 = new ArrayList<JdbcTypedValue>();
2103 for (Map.Entry<Column, JdbcTypedValue> updateValue
2104 : updateValues.entrySet())
2105 {
2106 Column column = updateValue.getKey();
2107 query.getSelectClause().add(column.getColumnName());
2108 replacementObjects.add(updateValue.getValue());
2109 }
2110
2111 PreparedStatement preparedStatement = null;
2112 try
2113 {
2114 preparedStatement = connection.prepareStatement(query.toString());
2115 int position = 1;
2116 for (JdbcTypedValue replacementObject : replacementObjects)
2117 {
2118 Object value = replacementObject.getValue();
2119 if (value != null)
2120 {
2121 preparedStatement.setObject(position, value);
2122 }
2123 else
2124 {
2125 preparedStatement.setNull(
2126 position,
2127 replacementObject.getJdbcType());
2128 }
2129 position++;
2130 }
2131 List<Object> replacements = setPreparedStatementReplacements(
2132 preparedStatement,
2133 query.getPreparedStatementReplacements(),
2134 position - 1);
2135 long startTime = System.currentTimeMillis();
2136 log.debug("Executing update " + query.toString()
2137 + " using update parameters " + replacementObjects
2138 + " and query parameters "
2139 + replacements);
2140
2141 int affectedRows = preparedStatement.executeUpdate();
2142 long queryEndTime = System.currentTimeMillis();
2143 log.trace("update took " + (queryEndTime - startTime)
2144 + " milliseconds");
2145
2146 preparedStatement.close();
2147 preparedStatement = null;
2148 return affectedRows;
2149 }
2150 catch (SQLException e)
2151 {
2152 final String dbName = updateValues.getDbName();
2153 final Adapter adapter = Torque.getAdapter(dbName);
2154 if (adapter != null)
2155 {
2156 throw adapter.toTorqueException(e);
2157 }
2158 throw new TorqueException(e);
2159 }
2160 finally
2161 {
2162 if (preparedStatement != null)
2163 {
2164 try
2165 {
2166 preparedStatement.close();
2167 }
2168 catch (SQLException e)
2169 {
2170 log.warn("error closing prepared statement", e);
2171 }
2172 }
2173 }
2174 }
2175
2176 /**
2177 * Utility method which executes a given sql statement. This
2178 * method should be used for update, insert, and delete
2179 * statements. Use executeQuery() for selects.
2180 *
2181 * @param statementString A String with the sql statement to execute.
2182 * @return The number of rows affected.
2183 * @throws TorqueException Any exceptions caught during processing will be
2184 * rethrown wrapped into a TorqueException.
2185 */
2186 public int executeStatement(String statementString) throws TorqueException
2187 {
2188 return executeStatement(statementString, Torque.getDefaultDB());
2189 }
2190
2191 /**
2192 * Utility method which executes a given sql statement. This
2193 * method should be used for update, insert, and delete
2194 * statements. Use executeQuery() for selects.
2195 *
2196 * @param statementString A String with the sql statement to execute.
2197 * @param dbName The name of the database to execute the statement against,
2198 * or null for the default DB.
2199 *
2200 * @return The number of rows affected.
2201 *
2202 * @throws TorqueException Any exceptions caught during processing will be
2203 * rethrown wrapped into a TorqueException.
2204 */
2205 public int executeStatement(String statementString, String dbName)
2206 throws TorqueException
2207 {
2208 Connection con = null;
2209 try
2210 {
2211 con = Transaction.begin(dbName);
2212 int rowCount = executeStatement(statementString, dbName,con);
2213 Transaction.commit(con);
2214 con = null;
2215 return rowCount;
2216 }
2217 finally
2218 {
2219 if (con != null)
2220 {
2221 Transaction.safeRollback(con);
2222 }
2223 }
2224 }
2225
2226 /**
2227 * Utility method which executes a given sql statement. This
2228 * method should be used for update, insert, and delete
2229 * statements. Use executeQuery() for selects.
2230 *
2231 * @param statementString A String with the sql statement to execute.
2232 * @param dbName The name of the database to execute the statement against,
2233 * or null for the default DB.
2234 * @param con The database connection to use.
2235 *
2236 * @return The number of rows affected.
2237 *
2238 * @throws TorqueException Any exceptions caught during processing will be
2239 * rethrown wrapped into a TorqueException.
2240 */
2241 public int executeStatement(
2242 String statementString,
2243 String dbName,
2244 Connection con)
2245 throws TorqueException
2246 {
2247 int rowCount = -1;
2248 Statement statement = null;
2249 try
2250 {
2251 statement = con.createStatement();
2252 rowCount = statement.executeUpdate(statementString);
2253 }
2254 catch (SQLException e)
2255 {
2256 throw new TorqueException(e);
2257 }
2258 finally
2259 {
2260 if (statement != null)
2261 {
2262 try
2263 {
2264 statement.close();
2265 }
2266 catch (SQLException e)
2267 {
2268 throw new TorqueException(e);
2269 }
2270 }
2271 }
2272 return rowCount;
2273 }
2274
2275 /**
2276 * Sets the prepared statement replacements into a query, possibly
2277 * modifying the type if required by DB Drivers.
2278 *
2279 * @param statement the statement to set the parameters in, not null.
2280 * @param replacements the replacements to set, not null.
2281 * @param offset the offset on the parameters, 0 for no offset.
2282 *
2283 * @return the parameters set.
2284 *
2285 * @throws SQLException if setting the parameter fails.
2286 */
2287 private List<Object> setPreparedStatementReplacements(
2288 PreparedStatement statement,
2289 List<Object> replacements,
2290 int offset)
2291 throws SQLException
2292 {
2293 List<Object> result = new ArrayList<Object>(replacements.size());
2294 int i = 1 + offset;
2295 for (Object param : replacements)
2296 {
2297 if (param instanceof java.sql.Timestamp)
2298 {
2299 statement.setTimestamp(i, (java.sql.Timestamp) param);
2300 result.add(param);
2301 }
2302 else if (param instanceof java.sql.Date)
2303 {
2304 statement.setDate(i, (java.sql.Date) param);
2305 result.add(param);
2306 }
2307 else if (param instanceof java.util.Date)
2308 {
2309 java.sql.Timestamp sqlDate = new java.sql.Timestamp(
2310 ((java.util.Date) param).getTime());
2311 statement.setTimestamp(i, sqlDate);
2312 result.add(sqlDate);
2313 }
2314 else if (param instanceof NumberKey)
2315 {
2316 BigDecimal bigDecimal = ((NumberKey) param).getBigDecimal();
2317 statement.setBigDecimal(i, bigDecimal);
2318 result.add(bigDecimal);
2319 }
2320 else if (param instanceof Integer)
2321 {
2322 statement.setInt(i, ((Integer) param).intValue());
2323 result.add(param);
2324 }
2325 else if (param instanceof Long)
2326 {
2327 statement.setLong(i, ((Long) param).longValue());
2328 result.add(param);
2329 }
2330 else if (param instanceof BigDecimal)
2331 {
2332 statement.setBigDecimal(i, (BigDecimal) param);
2333 result.add(param);
2334 }
2335 else if (param instanceof Boolean)
2336 {
2337 statement.setBoolean(i, ((Boolean) param).booleanValue());
2338 result.add(param);
2339 }
2340 else
2341 {
2342 statement.setString(i, param.toString());
2343 result.add(param.toString());
2344 }
2345 ++i;
2346 }
2347 return result;
2348 }
2349
2350 /**
2351 * Changes the boolean values in the criteria to the appropriate type,
2352 * whenever a booleanchar or booleanint column is involved.
2353 * This enables the user to create criteria using Boolean values
2354 * for booleanchar or booleanint columns.
2355 *
2356 * @param criteria the criteria in which the boolean values should be
2357 * corrected.
2358 * @throws TorqueException if the database map for the criteria cannot be
2359 * obtained.
2360 *
2361 * @deprecated Please use correctBooleans(
2362 * org.apache.torque.criteria.Criteria).
2363 * This method will be removed in a future version of Torque.
2364 */
2365 @Deprecated
2366 public void correctBooleans(Criteria criteria)
2367 throws TorqueException
2368 {
2369 for (Object criterionObject : criteria.values())
2370 {
2371 Criteria.Criterion criterion = (Criteria.Criterion) criterionObject;
2372 correctBooleans(criteria, criterion);
2373 }
2374 }
2375
2376 /**
2377 * Checks all columns in the criteria to see whether
2378 * booleanchar and booleanint columns are queried with a boolean.
2379 * If yes, the query values are mapped onto values the database
2380 * does understand, i.e. 0 and 1 for booleanints and N and Y for
2381 * booleanchar columns.
2382 *
2383 * @param criteria The criteria to which teh criterion belongs.
2384 * @param criterion The criterion to be checked for booleanint
2385 * and booleanchar columns.
2386 *
2387 * @throws TorqueException if the database map for the criteria cannot be
2388 * retrieved.
2389 *
2390 * @deprecated
2391 */
2392 @Deprecated
2393 private void correctBooleans(
2394 Criteria criteria,
2395 Criteria.Criterion criterion)
2396 throws TorqueException
2397 {
2398 Column column = criterion.getColumn();
2399 TableMap tableMapFromCriteria = MapHelper.getTableMap(
2400 column,
2401 criteria,
2402 tableMap);
2403 // if no description of table available, do not modify anything
2404 if (tableMapFromCriteria != null)
2405 {
2406 String columnName = column.getColumnName();
2407 ColumnMap columnMap = tableMapFromCriteria.getColumn(columnName);
2408 if (columnMap != null)
2409 {
2410 if ("BOOLEANINT".equals(columnMap.getTorqueType()))
2411 {
2412 replaceBooleanValues(
2413 criterion,
2414 Integer.valueOf(1),
2415 Integer.valueOf(0));
2416 }
2417 else if ("BOOLEANCHAR".equals(columnMap.getTorqueType()))
2418 {
2419 replaceBooleanValues(criterion, "Y", "N");
2420 }
2421 }
2422 }
2423 for (Criteria.Criterion attachedCriterion : criterion.getClauses())
2424 {
2425 correctBooleans(criteria, attachedCriterion);
2426 }
2427 }
2428
2429 /**
2430 * Checks all columns in the criteria to see whether
2431 * booleanchar and booleanint columns are queried with a boolean.
2432 * If yes, the query values are mapped onto values the database
2433 * does understand, i.e. 0 and 1 for booleanints and N and Y for
2434 * booleanchar columns.
2435 *
2436 * @param criteria The criteria to be checked for booleanint and booleanchar
2437 * columns.
2438 *
2439 * @throws TorqueException if the database map for the criteria cannot be
2440 * retrieved.
2441 */
2442 public void correctBooleans(
2443 org.apache.torque.criteria.Criteria criteria)
2444 throws TorqueException
2445 {
2446 correctBooleans(
2447 criteria,
2448 criteria.getTopLevelCriterion());
2449 }
2450
2451 private void correctBooleans(
2452 org.apache.torque.criteria.Criteria criteria,
2453 org.apache.torque.criteria.Criterion criterion)
2454 throws TorqueException
2455 {
2456 if (criterion == null)
2457 {
2458 return;
2459 }
2460 if (criterion.isComposite())
2461 {
2462 for (org.apache.torque.criteria.Criterion part
2463 : criterion.getParts())
2464 {
2465 correctBooleans(criteria, part);
2466 }
2467 return;
2468 }
2469
2470 Object possibleColumn = criterion.getLValue();
2471 TableMap tableMapForColumn = MapHelper.getTableMap(
2472 possibleColumn,
2473 criteria,
2474 tableMap);
2475 // if no description of table available, do not modify anything
2476 if (tableMapForColumn == null)
2477 {
2478 return;
2479 }
2480 String columnName = ((Column) possibleColumn).getColumnName();
2481 ColumnMap columnMap = tableMapForColumn.getColumn(columnName);
2482 if (columnMap != null)
2483 {
2484 if ("BOOLEANINT".equals(columnMap.getTorqueType()))
2485 {
2486 replaceBooleanValues(
2487 criterion,
2488 Integer.valueOf(1),
2489 Integer.valueOf(0));
2490 }
2491 else if ("BOOLEANCHAR".equals(columnMap.getTorqueType()))
2492 {
2493 replaceBooleanValues(criterion, "Y", "N");
2494 }
2495 }
2496 }
2497
2498 /**
2499 * Replaces any Boolean value in the criterion and its attached Criterions
2500 * by trueValue if the Boolean equals <code>Boolean.TRUE</code>
2501 * and falseValue if the Boolean equals <code>Boolean.FALSE</code>.
2502 *
2503 * @param criterion the criterion to replace Boolean values in.
2504 * @param trueValue the value by which Boolean.TRUE should be replaced.
2505 * @param falseValue the value by which Boolean.FALSE should be replaced.
2506 *
2507 * @deprecated
2508 */
2509 @Deprecated
2510 private void replaceBooleanValues(
2511 Criteria.Criterion criterion,
2512 Object trueValue,
2513 Object falseValue)
2514 {
2515 // attachedCriterions also contains the criterion itself,
2516 // so no additional treatment is needed for the criterion itself.
2517 Criteria.Criterion[] attachedCriterions
2518 = criterion.getAttachedCriterion();
2519 for (int i = 0; i < attachedCriterions.length; ++i)
2520 {
2521 Object criterionValue
2522 = attachedCriterions[i].getValue();
2523 if (criterionValue instanceof Boolean)
2524 {
2525 Boolean booleanValue = (Boolean) criterionValue;
2526 attachedCriterions[i].setValue(
2527 Boolean.TRUE.equals(booleanValue)
2528 ? trueValue
2529 : falseValue);
2530 }
2531
2532 }
2533 }
2534
2535 /**
2536 * Replaces any Boolean value in the criterion and its attached Criterions
2537 * by trueValue if the Boolean equals <code>Boolean.TRUE</code>
2538 * and falseValue if the Boolean equals <code>Boolean.FALSE</code>.
2539 *
2540 * @param criterion the criterion to replace Boolean values in.
2541 * May not be a composite criterion.
2542 * @param trueValue the value by which Boolean.TRUE should be replaced.
2543 * @param falseValue the value by which Boolean.FALSE should be replaced.
2544 */
2545 private void replaceBooleanValues(
2546 org.apache.torque.criteria.Criterion criterion,
2547 Object trueValue,
2548 Object falseValue)
2549 {
2550 Object rValue = criterion.getRValue();
2551 if (rValue instanceof Boolean)
2552 {
2553 Boolean booleanValue = (Boolean) rValue;
2554 criterion.setRValue(
2555 Boolean.TRUE.equals(booleanValue)
2556 ? trueValue
2557 : falseValue);
2558 }
2559 Object lValue = criterion.getLValue();
2560 if (lValue instanceof Boolean)
2561 {
2562 Boolean booleanValue = (Boolean) lValue;
2563 criterion.setLValue(
2564 Boolean.TRUE.equals(booleanValue)
2565 ? trueValue
2566 : falseValue);
2567 }
2568 }
2569
2570 /**
2571 * Checks all columns in the criteria to see whether
2572 * booleanchar and booleanint columns are queried with a boolean.
2573 * If yes, the query values are mapped onto values the database
2574 * does understand, i.e. 0 and 1 for booleanints and N and Y for
2575 * booleanchar columns.
2576 *
2577 * @param columnValues The value to be checked for booleanint
2578 * and booleanchar columns.
2579 * @throws TorqueException if the database map for the criteria cannot be
2580 * retrieved.
2581 */
2582 public void correctBooleans(
2583 ColumnValues columnValues)
2584 throws TorqueException
2585 {
2586 for (Map.Entry<Column, JdbcTypedValue> entry : columnValues.entrySet())
2587 {
2588 String columnName = entry.getKey().getColumnName();
2589 ColumnMap column = getTableMap().getColumn(columnName);
2590 if (column != null)
2591 {
2592 JdbcTypedValue columnValue = entry.getValue();
2593 if ("BOOLEANINT".equals(column.getTorqueType()))
2594 {
2595 if (Boolean.TRUE.equals(columnValue.getValue()))
2596 {
2597 entry.setValue(new JdbcTypedValue(1, Types.INTEGER));
2598 }
2599 else if (Boolean.FALSE.equals(columnValue.getValue()))
2600 {
2601 entry.setValue(new JdbcTypedValue(0, Types.INTEGER));
2602 }
2603 else if (columnValue.getValue() == null)
2604 {
2605 entry.setValue(new JdbcTypedValue(null, Types.INTEGER));
2606 }
2607 }
2608 else if ("BOOLEANCHAR".equals(column.getTorqueType()))
2609 {
2610 if (Boolean.TRUE.equals(columnValue.getValue()))
2611 {
2612 entry.setValue(new JdbcTypedValue("Y", Types.CHAR));
2613 }
2614 else if (Boolean.FALSE.equals(columnValue.getValue()))
2615 {
2616 entry.setValue(new JdbcTypedValue("N", Types.CHAR));
2617 }
2618 else if (columnValue.getValue() == null)
2619 {
2620 entry.setValue(new JdbcTypedValue(null, Types.CHAR));
2621 }
2622 }
2623 }
2624 }
2625 }
2626
2627 /**
2628 * Sets the database name in the passed criteria to the table's default,
2629 * if it is not already set.
2630 *
2631 * @param crit the criteria to set the database name in, not null.
2632 */
2633 protected void setDbName(org.apache.torque.criteria.Criteria crit)
2634 throws TorqueException
2635 {
2636 if (crit.getDbName() == null)
2637 {
2638 crit.setDbName(getDatabaseName());
2639 }
2640 }
2641
2642 /**
2643 * Sets the database name in the passed criteria to the table's default,
2644 * if it is not already set.
2645 *
2646 * @param crit the criteria to set the database name in, not null.
2647 *
2648 * @deprecated Please use addSelectColumns(
2649 * org.apache.torque.criteria.Criteria).
2650 * This method will be removed in a future version of Torque.
2651 */
2652 @Deprecated
2653 protected void setDbName(Criteria crit) throws TorqueException
2654 {
2655 if (crit.getDbName() == null)
2656 {
2657 crit.setDbName(getDatabaseName());
2658 }
2659 }
2660 }