Java tutorial
package org.apache.torque.util; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.io.Serializable; import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.torque.Column; import org.apache.torque.Database; import org.apache.torque.TooManyRowsException; import org.apache.torque.Torque; import org.apache.torque.TorqueException; import org.apache.torque.adapter.Adapter; import org.apache.torque.adapter.IDMethod; import org.apache.torque.criteria.FromElement; import org.apache.torque.map.ColumnMap; import org.apache.torque.map.MapHelper; import org.apache.torque.map.TableMap; import org.apache.torque.oid.IdGenerator; import org.apache.torque.om.NumberKey; import org.apache.torque.om.ObjectKey; import org.apache.torque.om.SimpleKey; import org.apache.torque.om.StringKey; import org.apache.torque.om.mapper.RecordMapper; import org.apache.torque.sql.Query; import org.apache.torque.sql.SqlBuilder; /** * This is the base class for all Peer classes in the system. Peer * classes are responsible for isolating all of the database access * for a specific business object. They execute all of the SQL * against the database. Over time this class has grown to include * utility methods which ease execution of cross-database queries and * the implementation of concrete Peers. * * @param <T> The data object class for this Peer. * * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a> * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a> * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a> * @author <a href="mailto:stephenh@chase3000.com">Stephen Haberman</a> * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a> * @author <a href="mailto:vido@ldh.org">Augustin Vidovic</a> * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> * @version $Id: BasePeerImpl.java 1415362 2012-11-29 20:33:52Z tfischer $ */ public class BasePeerImpl<T> implements Serializable { /** * Serial Version */ private static final long serialVersionUID = -7702123730779032381L; /** the log */ private static final Log log = LogFactory.getLog(BasePeerImpl.class); /** An injected instance of a record mapper to map JDBC result sets to objects */ private RecordMapper<T> recordMapper = null; /** An injected instance of a table map */ private TableMap tableMap = null; /** An injected instance of the database name */ private String databaseName = null; /** * Default constructor */ public BasePeerImpl() { super(); } /** * Constructor providing the objects to be injected as parameters. * * @param recordMapper a record mapper to map JDBC result sets to objects * @param tableMap the default table map * @param databaseName the name of the database */ public BasePeerImpl(RecordMapper<T> recordMapper, TableMap tableMap, String databaseName) { this(); setRecordMapper(recordMapper); setTableMap(tableMap); setDatabaseName(databaseName); } /** * Set the record mapper for this instance. * * @param recordMapper the recordMapper to set */ public void setRecordMapper(RecordMapper<T> recordMapper) { this.recordMapper = recordMapper; } /** * Get the record mapper for this instance. * * @return the recordMapper */ public RecordMapper<T> getRecordMapper() throws TorqueException { if (recordMapper == null) { throw new TorqueException("No record mapper injected"); } return recordMapper; } /** * Set the default table map for this instance. * * @param tableMap the tableMap to set */ public void setTableMap(TableMap tableMap) { this.tableMap = tableMap; } /** * Get the default table map for this instance. * * @return the tableMap */ public TableMap getTableMap() throws TorqueException { if (tableMap == null) { throw new TorqueException("No table map injected"); } return tableMap; } /** * Set the database name for this instance. * * @param databaseName the databaseName to set */ public void setDatabaseName(String databaseName) { this.databaseName = databaseName; } /** * Get the database name for this instance. * * @return the databaseName */ public String getDatabaseName() throws TorqueException { if (databaseName == null) { throw new TorqueException("No database name injected"); } return databaseName; } /** * Convenience method to create a String array of criteria keys. * * @param tableName Name of table. * @param columnNames A String[]. * @return A String[]. * * @deprecated This method is not used any more and will be removed in a * future version of Torque. */ @Deprecated public String[] initCriteriaKeys(String tableName, String[] columnNames) { String[] keys = new String[columnNames.length]; for (int i = 0; i < columnNames.length; i++) { keys[i] = tableName + "." + columnNames[i].toUpperCase(); } return keys; } /** * Convenience method that uses straight JDBC to delete multiple * rows. * * @param con A Connection. * @param table The table to delete records from. * @param column The column in the where clause. * @param value The value of the column. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated The value is not SQL escaped. * Better use doDelete(Criteria, String, Connection) * for automatic escaping and more flexibility. * This method will be removed in a future version of Torque. */ @Deprecated public int deleteAll(Connection con, String table, String column, int value) throws TorqueException { Statement statement = null; try { statement = con.createStatement(); StringBuffer query = new StringBuffer(); query.append("DELETE FROM ").append(table).append(" WHERE ").append(column).append(" = ").append(value); return statement.executeUpdate(query.toString()); } catch (SQLException e) { throw new TorqueException(e); } finally { if (statement != null) { try { statement.close(); } catch (SQLException e) { throw new TorqueException(e); } } } } /** * Convenience method that uses straight JDBC to delete multiple * rows. This method attempts to get the default database from * the pool. * * @param table The table to delete records from. * @param column The column in the where clause. * @param value The value of the column. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated The value is not SQL escaped. * Better use doDelete(Criteria, String) * for automatic escaping and more flexibility. * This method will be removed in a future version of Torque. */ @Deprecated public int deleteAll(String table, String column, int value) throws TorqueException { Connection con = null; try { con = Transaction.begin(Torque.getDefaultDB()); int result = deleteAll(con, table, column, value); Transaction.commit(con); con = null; return result; } finally { if (con != null) { Transaction.safeRollback(con); } } } /** * Deletes rows from a database table. * * @param criteria defines the rows to be deleted, not null. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int doDelete(org.apache.torque.criteria.Criteria criteria) throws TorqueException { Connection connection = null; try { setDbName(criteria); connection = Transaction.begin(criteria.getDbName()); int deletedRows = doDelete(criteria, connection); Transaction.commit(connection); connection = null; return deletedRows; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Deletes rows from a table. This method is to be used * during a transaction, otherwise use the doDelete(Criteria) method. * * @param criteria defines the rows to be deleted, not null. * @param connection the connection to use, not null. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int doDelete(org.apache.torque.criteria.Criteria criteria, Connection connection) throws TorqueException { correctBooleans(criteria); setDbName(criteria); Query query = SqlBuilder.buildQuery(criteria); query.setType(Query.Type.DELETE); String fullTableName; if (tableMap == null) { fullTableName = SqlBuilder.guessFullTableFromCriteria(criteria); } else { fullTableName = SqlBuilder.getFullTableName(tableMap.getFullyQualifiedTableName(), criteria.getDbName()); } boolean ownTableAdded = false; for (FromElement fromElement : query.getFromClause()) { // Table names are case insensitive in known databases // so use case-insensitive compare if (fullTableName.equalsIgnoreCase(fromElement.getFromExpression())) { ownTableAdded = true; break; } } if (!ownTableAdded) { query.getFromClause().add(new FromElement(fullTableName)); } String sql = query.toString(); PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(sql); List<Object> replacements = setPreparedStatementReplacements(preparedStatement, query.getPreparedStatementReplacements(), 0); long startTime = System.currentTimeMillis(); log.debug("Executing delete " + sql + ", parameters = " + replacements); int affectedRows = preparedStatement.executeUpdate(); long queryEndTime = System.currentTimeMillis(); log.trace("delete took " + (queryEndTime - startTime) + " milliseconds"); preparedStatement.close(); preparedStatement = null; return affectedRows; } catch (SQLException e) { throw ExceptionMapper.getInstance().toTorqueException(e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.warn("error closing prepared statement", e); } } } } /** * Method to perform deletes based on conditions in a Criteria. * * @param criteria The criteria to use. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated This method causes unexpected results when joins are used. * Please use doDelete( * org.apache.torque.criteria.Criteria, TableMap). * This method will be removed in a future version of Torque. */ @Deprecated protected int doDelete(Criteria criteria) throws TorqueException { Connection con = null; try { con = Transaction.begin(criteria.getDbName()); int result = doDelete(criteria, con); Transaction.commit(con); con = null; return result; } finally { if (con != null) { Transaction.safeRollback(con); } } } /** * Method to perform deletes based on conditions a Criteria. * * @param criteria The criteria to use. * @param con the Connection to be used for deleting. * * @return the number of deleted rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated This method causes unexpected results when joins are used. * Please use doDelete( * org.apache.torque.criteria.Criteria, TableMap, Connection). * This method will be removed in a future version of Torque. */ @Deprecated protected int doDelete(Criteria criteria, Connection con) throws TorqueException { if (criteria.values().isEmpty()) { throw new TorqueException("No conditions found in Criteria"); } Criteria.Criterion criterion = criteria.values().iterator().next(); TableMap tableMapFromCriteria = MapHelper.getTableMap(criterion.getColumn(), criteria, null); if (tableMapFromCriteria == null) { throw new TorqueException( "Unqualified column name in criteria" + " or table name not found in database map"); } Query query = SqlBuilder.buildQuery(criteria); query.setType(Query.Type.DELETE); String fullTableName = null; if (tableMap != null) { fullTableName = SqlBuilder.getFullTableName(tableMap.getFullyQualifiedTableName(), criteria.getDbName()); } else { Column column = criteria.values().iterator().next().getColumn(); fullTableName = SqlBuilder.getFullTableName(column.getFullTableName(), criteria.getDbName()); } boolean ownTableAdded = false; for (FromElement fromElement : query.getFromClause()) { // Table names are case insensitive in known databases // so use case-insensitive compare if (fullTableName.equalsIgnoreCase(fromElement.getFromExpression())) { ownTableAdded = true; break; } } if (!ownTableAdded) { query.getFromClause().add(new FromElement(fullTableName)); } String sql = query.toString(); PreparedStatement preparedStatement = null; try { preparedStatement = con.prepareStatement(sql); List<Object> replacements = setPreparedStatementReplacements(preparedStatement, query.getPreparedStatementReplacements(), 0); long startTime = System.currentTimeMillis(); log.debug("Executing delete " + sql + ", parameters = " + replacements); int affectedRows = preparedStatement.executeUpdate(); long queryEndTime = System.currentTimeMillis(); log.trace("delete took " + (queryEndTime - startTime) + " milliseconds"); preparedStatement.close(); preparedStatement = null; return affectedRows; } catch (SQLException e) { throw ExceptionMapper.getInstance().toTorqueException(e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.warn("error closing prepared statement", e); } } } } /** * Inserts a record into a database table. * <p> * If the primary key is included in Criteria, then that value will * be used to insert the row. * <p> * Otherwise, if the primary key can be generated automatically, * the generated key will be used for the insert and will be returned. * <p> * If no value is given for the primary key is defined and it cannot * be generated automatically or the table has no primary key, * the values will be inserted as specified and null will be returned. * * @param insertValues Contains the values to insert, not null. * * @return the primary key of the inserted row (if the table * has a primary key) or null (if the table does not have * a primary key). * * @throws TorqueException if a database error occurs. */ public ObjectKey doInsert(ColumnValues insertValues) throws TorqueException { String databaseNameFromInsertValues = insertValues.getDbName(); if (databaseNameFromInsertValues == null) { databaseNameFromInsertValues = getDatabaseName(); } Connection connection = null; try { connection = Transaction.begin(databaseNameFromInsertValues); ObjectKey id = doInsert(insertValues, connection); Transaction.commit(connection); connection = null; return id; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Inserts a record into a database table. * <p> * If the primary key is included in Criteria, then that value will * be used to insert the row. * <p> * Otherwise, if the primary key can be generated automatically, * the generated key will be used for the insert and will be returned. * <p> * If no value is given for the primary key is defined and it cannot * be generated automatically or the table has no primary key, * the values will be inserted as specified and null will be returned. * * @param insertValues Contains the values to insert, not null. * @param connection the connection to use for the insert, not null. * * @return the primary key of the inserted row (if the table * has a primary key) or null (if the table does not have * a primary key). * * @throws TorqueException if a database error occurs. */ public ObjectKey doInsert(ColumnValues insertValues, Connection connection) throws TorqueException { if (insertValues == null) { throw new TorqueException("insertValues is null"); } if (connection == null) { throw new TorqueException("connection is null"); } String databaseNameFromInsertValues = insertValues.getDbName(); if (databaseNameFromInsertValues == null) { databaseNameFromInsertValues = getDatabaseName(); } Database database = Torque.getDatabase(databaseNameFromInsertValues); Object keyInfo = getIdMethodInfo(); IdGenerator keyGen = database.getIdGenerator(getTableMap().getPrimaryKeyMethod()); SimpleKey id = null; // can currently generate only single column pks, therefore a single // columnMap is ok ColumnMap primaryKey = null; if (keyGen != null) { // fail on multiple pks primaryKey = getTableMap().getPrimaryKey(); // primaryKey will be null if there is no primary key // defined for the table we're inserting into. if (keyGen.isPriorToInsert() && primaryKey != null && !insertValues.containsKey(primaryKey)) { id = getId(primaryKey, keyGen, connection, keyInfo); insertValues.put(primaryKey, new JdbcTypedValue(id.getValue(), id.getJdbcType())); } } List<String> columnNames = new ArrayList<String>(); List<JdbcTypedValue> replacementObjects = new ArrayList<JdbcTypedValue>(); for (Map.Entry<Column, JdbcTypedValue> columnValue : insertValues.entrySet()) { Column column = columnValue.getKey(); columnNames.add(column.getColumnName()); JdbcTypedValue value = columnValue.getValue(); replacementObjects.add(value); } String fullTableName = SqlBuilder.getFullTableName(getTableMap().getFullyQualifiedTableName(), databaseNameFromInsertValues); StringBuilder query = new StringBuilder("INSERT INTO ").append(fullTableName).append("(") .append(StringUtils.join(columnNames, ",")).append(") VALUES ("); for (int i = 0; i < columnNames.size(); ++i) { if (i != 0) { query.append(","); } query.append("?"); } query.append(")"); PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(query.toString()); int position = 1; for (JdbcTypedValue replacementObject : replacementObjects) { Object value = replacementObject.getValue(); if (value != null) { if (replacementObject.getJdbcType() != Types.BLOB && replacementObject.getJdbcType() != Types.CLOB) { preparedStatement.setObject(position, value, replacementObject.getJdbcType()); } else { preparedStatement.setObject(position, value); } } else { preparedStatement.setNull(position, replacementObject.getJdbcType()); } position++; } long startTime = System.currentTimeMillis(); log.debug("Executing insert " + query.toString() + " using parameters " + replacementObjects); preparedStatement.executeUpdate(); long queryEndTime = System.currentTimeMillis(); log.trace("insert took " + (queryEndTime - startTime) + " milliseconds"); preparedStatement.close(); preparedStatement = null; } catch (SQLException e) { throw ExceptionMapper.getInstance().toTorqueException(e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.warn("error closing prepared statement", e); } } } // If the primary key column is auto-incremented, get the id // now. if (keyGen != null && keyGen.isPostInsert() && primaryKey != null && !insertValues.containsKey(primaryKey)) { id = getId(primaryKey, keyGen, connection, keyInfo); } return id; } /** * Returns the idMethodInfo for the table for this Peer class. * * @return the idMethodInfo, not null. * * @throws TorqueException if the database adapter for the table's database * needs to be accessed but is not configured. */ private Object getIdMethodInfo() throws TorqueException { IDMethod idMethod = tableMap.getPrimaryKeyMethod(); if (IDMethod.NATIVE == idMethod) { Adapter adapter = Torque.getAdapter(getDatabaseName()); if (adapter == null) { throw new TorqueException("missing adapter configuration for database " + getDatabaseName() + "check the Torque configuration"); } idMethod = adapter.getIDMethodType(); } Object keyInfo = tableMap.getPrimaryKeyMethodInfo(idMethod); return keyInfo; } /** * Create an Id for insertion in the Criteria * * @param pk ColumnMap for the Primary key * @param keyGen The Id Generator object * @param con The SQL Connection to run the id generation under * @param keyInfo KeyInfo Parameter from the Table map * * @return A simple Key representing the new Id value * @throws TorqueException Possible errors get wrapped in here. */ private SimpleKey getId(ColumnMap pk, IdGenerator keyGen, Connection con, Object keyInfo) throws TorqueException { SimpleKey id = null; if (pk != null && keyGen != null) { if (pk.getType() instanceof Number) { id = new NumberKey(keyGen.getIdAsBigDecimal(con, keyInfo)); } else { id = new StringKey(keyGen.getIdAsString(con, keyInfo)); } } return id; } /** * Add all the columns needed to create a new object. * * @param criteria the Criteria to which the select columns should * be added. */ public void addSelectColumns(org.apache.torque.criteria.Criteria criteria) { ColumnMap[] columns = this.tableMap.getColumns(); for (ColumnMap c : columns) { criteria.addSelectColumn(c); } } /** * Add all the columns needed to create a new object. * * @param criteria the Criteria to which the select columns should * be added. * * @deprecated Please use addSelectColumns( * org.apache.torque.criteria.Criteria). * This method will be removed in a future version of Torque. */ @Deprecated public void addSelectColumns(Criteria criteria) { ColumnMap[] columns = this.tableMap.getColumns(); for (ColumnMap c : columns) { criteria.addSelectColumn(c); } } /** * Selects objects from a database. * * @param criteria object used to create the SELECT statement. * * @return the list of selected objects, not null. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated Please use doSelect(org.apache.torque.criteria.Criteria). * This method will be removed in a future version of Torque. */ @Deprecated public List<T> doSelect(Criteria criteria) throws TorqueException { if (criteria.getSelectColumns().size() == 0) { addSelectColumns(criteria); } setDbName(criteria); return doSelect(criteria, getRecordMapper()); } /** * Selects objects from a database. * * @param criteria object used to create the SELECT statement. * * @return the list of selected objects, not null. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public List<T> doSelect(org.apache.torque.criteria.Criteria criteria) throws TorqueException { if (criteria.getSelectColumns().size() == 0) { addSelectColumns(criteria); } setDbName(criteria); return doSelect(criteria, getRecordMapper()); } /** * Selects objects from a database * within a transaction. * * @param criteria object used to create the SELECT statement. * @param connection the connection to use, not null. * * @return the list of selected objects, not null. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. * * @deprecated Please use doSelect(org.apache.torque.criteria.Criteria, * Connection). * This method will be removed in a future version of Torque. */ @Deprecated public List<T> doSelect(Criteria criteria, Connection connection) throws TorqueException { if (criteria.getSelectColumns().size() == 0) { addSelectColumns(criteria); } setDbName(criteria); return doSelect(criteria, getRecordMapper(), connection); } /** * Selects objects from a database * within a transaction. * * @param criteria object used to create the SELECT statement. * @param connection the connection to use, not null. * * @return the list of selected objects, not null. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public List<T> doSelect(org.apache.torque.criteria.Criteria criteria, Connection connection) throws TorqueException { if (criteria.getSelectColumns().size() == 0) { addSelectColumns(criteria); } setDbName(criteria); return doSelect(criteria, getRecordMapper(), connection); } /** * Selects at most one object from a database. * * @param criteria object used to create the SELECT statement. * * @return the selected Object, or null if no object was selected. * * @throws TorqueException If more than one record is selected or if * an error occurs when processing the query. */ public T doSelectSingleRecord(org.apache.torque.criteria.Criteria criteria) throws TorqueException { List<T> recordList = doSelect(criteria); T record = null; if (recordList.size() > 1) { throw new TooManyRowsException("Criteria " + criteria + " matched more than one record"); } if (!recordList.isEmpty()) { record = recordList.get(0); } return record; } /** * Selects at most one object from a database * within a transaction. * * @param criteria object used to create the SELECT statement. * @param connection the connection holding the transaction, not null. * * @return the selected Object, or null if no object was selected. * * @throws TorqueException If more than one record is selected or if * an error occurs when processing the query. */ public T doSelectSingleRecord(org.apache.torque.criteria.Criteria criteria, Connection connection) throws TorqueException { List<T> recordList = doSelect(criteria, connection); T record = null; if (recordList.size() > 1) { throw new TooManyRowsException("Criteria " + criteria + " matched more than one record"); } if (!recordList.isEmpty()) { record = recordList.get(0); } return record; } /** * Selects rows from a database an maps them to objects. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * * @return The results of the query, not null. * * @throws TorqueException if querying the database fails. * * @deprecated Please use doSelect(org.apache.torque.criteria.Criteria, * RecordMapper). * This method will be removed in a future version of Torque. */ @Deprecated public <TT> List<TT> doSelect(Criteria criteria, RecordMapper<TT> mapper) throws TorqueException { Connection connection = null; try { connection = Transaction.begin(criteria.getDbName()); List<TT> result = doSelect(criteria, mapper, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Selects rows from a database an maps them to objects. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * * @return The results of the query, not null. * * @throws TorqueException if querying the database fails. */ public <TT> List<TT> doSelect(org.apache.torque.criteria.Criteria criteria, RecordMapper<TT> mapper) throws TorqueException { Connection connection = null; try { connection = Transaction.begin(criteria.getDbName()); List<TT> result = doSelect(criteria, mapper, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Selects rows from a database an maps them to objects. * * @param query the sql query to execute, not null. * * @return The results of the query, not null. * * @throws TorqueException if querying the database fails. */ public List<T> doSelect(String query) throws TorqueException { return doSelect(query, getRecordMapper(), getDatabaseName()); } /** * Selects rows from a database an maps them to objects. * * @param query the SQL Query to execute, not null. * @param connection the database connection, not null. * * @return The results of the query, not null. * * @throws TorqueException if querying the database fails. */ public List<T> doSelect(String query, Connection connection) throws TorqueException { return doSelect(query, getRecordMapper(), connection); } /** * Selects rows from a database an maps them to objects. * * @param query the sql query to execute, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param dbName The name of the database to create the connection for, * or null for the default DB. * * @return The results of the query, not null. * * @throws TorqueException if querying the database fails. */ public <TT> List<TT> doSelect(String query, RecordMapper<TT> mapper, String dbName) throws TorqueException { Connection connection = null; try { connection = Transaction.begin((dbName == null) ? Torque.getDefaultDB() : dbName); List<TT> result = doSelect(query, mapper, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Selects rows from a database an maps them to objects. * * @param query the SQL Query to execute, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param connection the database connection, not null. * * @return The results of the query, not null. * * @throws TorqueException if querying the database fails. */ public <TT> List<TT> doSelect(String query, RecordMapper<TT> mapper, Connection connection) throws TorqueException { if (connection == null) { throw new NullPointerException("connection is null"); } List<TT> result = new ArrayList<TT>(); Statement statement = null; ResultSet resultSet = null; try { statement = connection.createStatement(); long startTime = System.currentTimeMillis(); log.debug("Executing query " + query); resultSet = statement.executeQuery(query.toString()); long queryEndTime = System.currentTimeMillis(); log.trace("query took " + (queryEndTime - startTime) + " milliseconds"); while (resultSet.next()) { TT rowResult = mapper.processRow(resultSet, 0, null); result.add(rowResult); } long mappingEndTime = System.currentTimeMillis(); log.trace("mapping took " + (mappingEndTime - queryEndTime) + " milliseconds"); } catch (SQLException e) { throw ExceptionMapper.getInstance().toTorqueException(e); } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { log.warn("error closing resultSet", e); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { log.warn("error closing statement", e); } } } return result; } /** * Performs a SQL <code>select</code> using a PreparedStatement. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param connection the database connection for selecting records, * not null. * * @return The results of the query, not null. * * @throws TorqueException Error performing database query. * * @deprecated Please use doSelect(org.apache.torque.criteria.Criteria, * RecordMapper, Connection). * This method will be removed in a future version of Torque. */ @Deprecated public <TT> List<TT> doSelect(Criteria criteria, RecordMapper<TT> mapper, Connection connection) throws TorqueException { correctBooleans(criteria); Query query = SqlBuilder.buildQuery(criteria); if (query.getFromClause().isEmpty()) { String tableName = SqlBuilder.getFullTableName(getTableMap().getFullyQualifiedTableName(), criteria.getDbName()); query.getFromClause().add(new FromElement(tableName)); } PreparedStatement statement = null; ResultSet resultSet = null; try { statement = connection.prepareStatement(query.toString()); List<Object> replacements = setPreparedStatementReplacements(statement, query.getPreparedStatementReplacements(), 0); long startTime = System.currentTimeMillis(); log.debug("Executing query " + query + ", parameters = " + replacements); resultSet = statement.executeQuery(); long queryEndTime = System.currentTimeMillis(); log.trace("query took " + (queryEndTime - startTime) + " milliseconds"); long offset; Database database = Torque.getDatabase(criteria.getDbName()); if (database.getAdapter().supportsNativeOffset()) { offset = 0; //database takes care of offset } else { offset = criteria.getOffset(); } long limit; if (database.getAdapter().supportsNativeLimit()) { limit = -1; //database takes care of offset } else { if (database.getAdapter().supportsNativeOffset()) { limit = criteria.getLimit(); } else { if (criteria.getLimit() == -1) { limit = criteria.getLimit(); } else { limit = offset + criteria.getLimit(); } } } List<TT> result = new ArrayList<TT>(); int rowNumber = 0; while (resultSet.next()) { if (rowNumber < offset) { rowNumber++; continue; } if (limit >= 0 && rowNumber >= limit) { break; } TT rowResult = mapper.processRow(resultSet, 0, criteria); result.add(rowResult); rowNumber++; } long mappingEndTime = System.currentTimeMillis(); log.trace("mapping took " + (mappingEndTime - queryEndTime) + " milliseconds"); if (criteria.isSingleRecord() && result.size() > 1) { throw new TooManyRowsException( "Criteria expected single Record and " + "Multiple Records were selected"); } return result; } catch (SQLException e) { throw ExceptionMapper.getInstance().toTorqueException(e); } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { log.warn("error closing resultSet", e); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { log.warn("error closing statement", e); } } } } /** * Performs a SQL <code>select</code> using a PreparedStatement. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param connection the database connection for selecting records, * not null. * * @return The results of the query, not null. * * @throws TorqueException Error performing database query. */ public <TT> List<TT> doSelect(org.apache.torque.criteria.Criteria criteria, RecordMapper<TT> mapper, Connection connection) throws TorqueException { correctBooleans(criteria); Query query = SqlBuilder.buildQuery(criteria); if (query.getFromClause().isEmpty()) { String tableName = SqlBuilder.getFullTableName(getTableMap().getFullyQualifiedTableName(), criteria.getDbName()); query.getFromClause().add(new FromElement(tableName)); } PreparedStatement statement = null; ResultSet resultSet = null; try { statement = connection.prepareStatement(query.toString()); if (query.getFetchSize() != null) { statement.setFetchSize(query.getFetchSize()); } List<Object> replacements = setPreparedStatementReplacements(statement, query.getPreparedStatementReplacements(), 0); long startTime = System.currentTimeMillis(); log.debug("Executing query " + query + ", parameters = " + replacements); resultSet = statement.executeQuery(); long queryEndTime = System.currentTimeMillis(); log.trace("query took " + (queryEndTime - startTime) + " milliseconds"); long offset; Database database = Torque.getDatabase(criteria.getDbName()); if (database.getAdapter().supportsNativeOffset()) { offset = 0; //database takes care of offset } else { offset = criteria.getOffset(); } long limit; if (database.getAdapter().supportsNativeLimit()) { limit = -1; //database takes care of offset } else { if (database.getAdapter().supportsNativeOffset()) { limit = criteria.getLimit(); } else { if (criteria.getLimit() == -1) { limit = criteria.getLimit(); } else { limit = offset + criteria.getLimit(); } } } List<TT> result = new ArrayList<TT>(); int rowNumber = 0; while (resultSet.next()) { if (rowNumber < offset) { rowNumber++; continue; } if (limit >= 0 && rowNumber >= limit) { break; } TT rowResult = mapper.processRow(resultSet, 0, criteria); result.add(rowResult); rowNumber++; } long mappingEndTime = System.currentTimeMillis(); log.trace("mapping took " + (mappingEndTime - queryEndTime) + " milliseconds"); if (criteria.isSingleRecord() && result.size() > 1) { throw new TooManyRowsException( "Criteria expected single Record and " + "Multiple Records were selected"); } return result; } catch (SQLException e) { throw ExceptionMapper.getInstance().toTorqueException(e); } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { log.warn("error closing resultSet", e); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { log.warn("error closing statement", e); } } } } /** * Selects at most a single row from a database an maps them to objects. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * * @return The selected row, or null if no records was selected. * * @throws TorqueException if querying the database fails. */ public <TT> TT doSelectSingleRecord(org.apache.torque.criteria.Criteria criteria, RecordMapper<TT> mapper) throws TorqueException { List<TT> resultList = doSelect(criteria, mapper); TT result = null; if (resultList.size() > 1) { throw new TooManyRowsException("Criteria " + criteria + " matched more than one record"); } if (!resultList.isEmpty()) { result = resultList.get(0); } return result; } /** * Selects at most a single row from a database an maps them to objects. * * @param criteria A Criteria specifying the records to select, not null. * @param mapper The mapper creating the objects from the resultSet, * not null. * @param connection the database connection, not null. * * @return The selected row, or null if no records was selected. * * @throws TorqueException if querying the database fails. */ public <TT> TT doSelectSingleRecord(org.apache.torque.criteria.Criteria criteria, RecordMapper<TT> mapper, Connection connection) throws TorqueException { List<TT> resultList = doSelect(criteria, mapper, connection); TT result = null; if (resultList.size() > 1) { throw new TooManyRowsException("Criteria " + criteria + " matched more than one record"); } if (!resultList.isEmpty()) { result = resultList.get(0); } return result; } /** * Convenience method used to update rows in the DB. Checks if a * <i>single</i> primary key is specified in the Criteria * object and uses it to perform the update. If no primary key is * specified or the table has multiple primary keys, * an Exception will be thrown. * <p> * Use this method for performing an update of the kind: * <p> * "WHERE primary_key_id = someValue" * <p> * To perform an update on a table with multiple primary keys or * an update with non-primary key fields in the WHERE * clause, use doUpdate(ColumnValues, Criteria). * * @param updateValues Which columns to update with which values * for which primary key value, not null. * * @return the number of affected rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int doUpdate(ColumnValues updateValues) throws TorqueException { String databaseNameFromUpdateValues = updateValues.getDbName(); if (databaseNameFromUpdateValues == null) { databaseNameFromUpdateValues = getDatabaseName(); } Connection connection = null; try { connection = Transaction.begin(databaseNameFromUpdateValues); int result = doUpdate(updateValues, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Convenience method used to update rows in the DB. Checks if a * <i>single</i> primary key is specified in the Criteria * object and uses it to perform the update. If no primary key is * specified or the table has multiple primary keys, * an Exception will be thrown. * <p> * Use this method for performing an update of the kind: * <p> * "WHERE primary_key_id = someValue" * <p> * To perform an update on a table with multiple primary keys or * an update with non-primary key fields in the WHERE * clause, use doUpdate(ColumnValues, Criteria, Connection). * * @param updateValues Which columns to update with which values * for which primary key value, not null. * @param connection the database connection to use. * * @return the number of affected rows. * * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ public int doUpdate(ColumnValues updateValues, Connection connection) throws TorqueException { ColumnMap pk = getTableMap().getPrimaryKey(); org.apache.torque.criteria.Criteria selectCriteria = null; if (pk != null && updateValues.containsKey(pk.getSqlExpression())) { selectCriteria = new org.apache.torque.criteria.Criteria(); selectCriteria.where(pk, updateValues.remove(pk.getSqlExpression())); } else { throw new TorqueException("No PK specified for database update"); } return doUpdate(selectCriteria, updateValues, connection); } /** * Executes an update against the database. The rows to be updated * are selected using <code>criteria</code> and updated using the values * in <code>updateValues</code>. * * @param selectCriteria selects which rows of which table * should be updated, not null. * @param updateValues Which columns to update with which values, not null. * * @return the number of affected rows. * * @throws TorqueException if updating fails. * * @deprecated Please use doUpdate( * org.apache.torque.criteria.Criteria, ColumnValues). * This method will be removed in a future version of Torque. */ @Deprecated public int doUpdate(Criteria selectCriteria, ColumnValues updateValues) throws TorqueException { String databaseNameFromUpdateValues = updateValues.getDbName(); if (databaseNameFromUpdateValues == null) { databaseNameFromUpdateValues = getDatabaseName(); } Connection connection = null; try { connection = Transaction.begin(databaseNameFromUpdateValues); int result = doUpdate(selectCriteria, updateValues, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Executes an update against the database. The rows to be updated * are selected using <code>criteria</code> and updated using the values * in <code>updateValues</code>. * * @param selectCriteria selects which rows of which table * should be updated, not null. * @param updateValues Which columns to update with which values, not null. * * @return the number of affected rows. * * @throws TorqueException if updating fails. */ public int doUpdate(org.apache.torque.criteria.Criteria selectCriteria, ColumnValues updateValues) throws TorqueException { String databaseNameFromUpdateValues = updateValues.getDbName(); if (databaseNameFromUpdateValues == null) { databaseNameFromUpdateValues = getDatabaseName(); } Connection connection = null; try { connection = Transaction.begin(databaseNameFromUpdateValues); int result = doUpdate(selectCriteria, updateValues, connection); Transaction.commit(connection); connection = null; return result; } finally { if (connection != null) { Transaction.safeRollback(connection); } } } /** * Executes an update against the database. The rows to be updated * are selected using <code>criteria</code> and updated using the values * in <code>updateValues</code>. * * @param criteria selects which rows of which table should be updated. * @param updateValues Which columns to update with which values, not null. * @param connection the database connection to use, not null. * * @return the number of affected rows. * * @throws TorqueException if updating fails. * * @deprecated Please use doUpdate(org.apache.torque.criteria.Criteria, * ColumnValues, Connection). * This method will be removed in a future version of Torque. */ @Deprecated public int doUpdate(Criteria criteria, ColumnValues updateValues, Connection connection) throws TorqueException { Query query = SqlBuilder.buildQuery(criteria); query.setType(Query.Type.UPDATE); query.getFromClause().clear(); String fullTableName = SqlBuilder.getFullTableName(getTableMap().getFullyQualifiedTableName(), criteria.getDbName()); query.getFromClause().add(new FromElement(fullTableName)); List<JdbcTypedValue> replacementObjects = new ArrayList<JdbcTypedValue>(); for (Map.Entry<Column, JdbcTypedValue> updateValue : updateValues.entrySet()) { Column column = updateValue.getKey(); query.getSelectClause().add(column.getColumnName()); replacementObjects.add(updateValue.getValue()); } PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(query.toString()); int position = 1; for (JdbcTypedValue replacementObject : replacementObjects) { Object value = replacementObject.getValue(); if (value != null) { preparedStatement.setObject(position, value); } else { preparedStatement.setNull(position, replacementObject.getJdbcType()); } position++; } List<Object> replacements = setPreparedStatementReplacements(preparedStatement, query.getPreparedStatementReplacements(), position - 1); long startTime = System.currentTimeMillis(); log.debug("Executing update " + query.toString() + " using update parameters " + replacementObjects + " and query parameters " + replacements); int affectedRows = preparedStatement.executeUpdate(); long queryEndTime = System.currentTimeMillis(); log.trace("update took " + (queryEndTime - startTime) + " milliseconds"); preparedStatement.close(); preparedStatement = null; return affectedRows; } catch (SQLException e) { throw ExceptionMapper.getInstance().toTorqueException(e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.warn("error closing prepared statement", e); } } } } /** * Executes an update against the database. The rows to be updated * are selected using <code>criteria</code> and updated using the values * in <code>updateValues</code>. * * @param criteria selects which rows of which table should be updated. * @param updateValues Which columns to update with which values, not null. * @param connection the database connection to use, not null. * * @return the number of affected rows. * * @throws TorqueException if updating fails. */ public int doUpdate(org.apache.torque.criteria.Criteria criteria, ColumnValues updateValues, Connection connection) throws TorqueException { Query query = SqlBuilder.buildQuery(criteria); query.setType(Query.Type.UPDATE); query.getFromClause().clear(); String fullTableName = SqlBuilder.getFullTableName(getTableMap().getFullyQualifiedTableName(), criteria.getDbName()); query.getFromClause().add(new FromElement(fullTableName)); List<JdbcTypedValue> replacementObjects = new ArrayList<JdbcTypedValue>(); for (Map.Entry<Column, JdbcTypedValue> updateValue : updateValues.entrySet()) { Column column = updateValue.getKey(); query.getSelectClause().add(column.getColumnName()); replacementObjects.add(updateValue.getValue()); } PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(query.toString()); int position = 1; for (JdbcTypedValue replacementObject : replacementObjects) { Object value = replacementObject.getValue(); if (value != null) { preparedStatement.setObject(position, value); } else { preparedStatement.setNull(position, replacementObject.getJdbcType()); } position++; } List<Object> replacements = setPreparedStatementReplacements(preparedStatement, query.getPreparedStatementReplacements(), position - 1); long startTime = System.currentTimeMillis(); log.debug("Executing update " + query.toString() + " using update parameters " + replacementObjects + " and query parameters " + replacements); int affectedRows = preparedStatement.executeUpdate(); long queryEndTime = System.currentTimeMillis(); log.trace("update took " + (queryEndTime - startTime) + " milliseconds"); preparedStatement.close(); preparedStatement = null; return affectedRows; } catch (SQLException e) { throw ExceptionMapper.getInstance().toTorqueException(e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.warn("error closing prepared statement", e); } } } } /** * Utility method which executes a given sql statement * as prepared statement. * This method should be used for update, insert, and delete statements. * Use executeQuery() for selects. * * @param statementString A String with the sql statement to execute. * * @return The number of rows affected. * * @throws TorqueException if executing the statement fails * or no database connection can be established. */ public int executeStatement(String statementString) throws TorqueException { return executeStatement(statementString, Torque.getDefaultDB(), null); } /** * Utility method which executes a given sql statement * as prepared statement. * This method should be used for update, insert, and delete statements. * Use executeQuery() for selects. * * @param statementString A String with the sql statement to execute. * @param replacementValues values to use as placeholders in the query. * or null or empty if no placeholders need to be filled. * * @return The number of rows affected. * * @throws TorqueException if executing the statement fails * or no database connection can be established. */ public int executeStatement(String statementString, List<JdbcTypedValue> replacementValues) throws TorqueException { return executeStatement(statementString, Torque.getDefaultDB(), replacementValues); } /** * Utility method which executes a given sql statement * as prepared statement. * This method should be used for update, insert, and delete statements. * Use executeQuery() for selects. * * @param statementString A String with the sql statement to execute. * @param dbName The name of the database to execute the statement against, * or null for the default DB. * @param replacementValues values to use as placeholders in the query. * or null or empty if no placeholders need to be filled. * * @return The number of rows affected. * * @throws TorqueException if executing the statement fails * or no database connection can be established. */ public int executeStatement(String statementString, String dbName, List<JdbcTypedValue> replacementValues) throws TorqueException { Connection con = null; try { con = Transaction.begin(dbName); int rowCount = executeStatement(statementString, con, replacementValues); Transaction.commit(con); con = null; return rowCount; } finally { if (con != null) { Transaction.safeRollback(con); } } } /** * Utility method which executes a given sql statement * as prepared statement. * This method should be used for update, insert, and delete statements. * Use executeQuery() for selects. * * @param statementString A String with the sql statement to execute. * @param con The database connection to use. * @param replacementValues values to use as placeholders in the query. * or null or empty if no placeholders need to be filled. * * @return The number of rows affected. * * @throws TorqueException if executing the statement fails. */ public int executeStatement(String statementString, Connection con, List<JdbcTypedValue> replacementValues) throws TorqueException { int rowCount = -1; PreparedStatement statement = null; try { statement = con.prepareStatement(statementString); if (replacementValues != null) { int position = 1; for (JdbcTypedValue replacementValue : replacementValues) { if (replacementValue.getValue() == null) { statement.setNull(position, replacementValue.getJdbcType()); } else { statement.setObject(position, replacementValue.getValue(), replacementValue.getJdbcType()); } ++position; } } rowCount = statement.executeUpdate(); } catch (SQLException e) { throw new TorqueException(e); } finally { if (statement != null) { try { statement.close(); } catch (SQLException e) { throw new TorqueException(e); } } } return rowCount; } /** * Sets the prepared statement replacements into a query, possibly * modifying the type if required by DB Drivers. * * @param statement the statement to set the parameters in, not null. * @param replacements the replacements to set, not null. * @param offset the offset on the parameters, 0 for no offset. * * @return the parameters set. * * @throws SQLException if setting the parameter fails. */ private List<Object> setPreparedStatementReplacements(PreparedStatement statement, List<Object> replacements, int offset) throws SQLException { List<Object> result = new ArrayList<Object>(replacements.size()); int i = 1 + offset; for (Object param : replacements) { if (param instanceof java.sql.Timestamp) { statement.setTimestamp(i, (java.sql.Timestamp) param); result.add(param); } else if (param instanceof java.sql.Date) { statement.setDate(i, (java.sql.Date) param); result.add(param); } else if (param instanceof java.util.Date) { java.sql.Timestamp sqlDate = new java.sql.Timestamp(((java.util.Date) param).getTime()); statement.setTimestamp(i, sqlDate); result.add(sqlDate); } else if (param instanceof NumberKey) { BigDecimal bigDecimal = ((NumberKey) param).getBigDecimal(); statement.setBigDecimal(i, bigDecimal); result.add(bigDecimal); } else if (param instanceof Integer) { statement.setInt(i, ((Integer) param).intValue()); result.add(param); } else if (param instanceof Long) { statement.setLong(i, ((Long) param).longValue()); result.add(param); } else if (param instanceof BigDecimal) { statement.setBigDecimal(i, (BigDecimal) param); result.add(param); } else if (param instanceof Boolean) { statement.setBoolean(i, ((Boolean) param).booleanValue()); result.add(param); } else { statement.setString(i, param.toString()); result.add(param.toString()); } ++i; } return result; } /** * Changes the boolean values in the criteria to the appropriate type, * whenever a booleanchar or booleanint column is involved. * This enables the user to create criteria using Boolean values * for booleanchar or booleanint columns. * * @param criteria the criteria in which the boolean values should be * corrected. * @throws TorqueException if the database map for the criteria cannot be * obtained. * * @deprecated Please use correctBooleans( * org.apache.torque.criteria.Criteria). * This method will be removed in a future version of Torque. */ @Deprecated public void correctBooleans(Criteria criteria) throws TorqueException { for (Object criterionObject : criteria.values()) { Criteria.Criterion criterion = (Criteria.Criterion) criterionObject; correctBooleans(criteria, criterion); } } /** * Checks all columns in the criteria to see whether * booleanchar and booleanint columns are queried with a boolean. * If yes, the query values are mapped onto values the database * does understand, i.e. 0 and 1 for booleanints and N and Y for * booleanchar columns. * * @param criteria The criteria to which teh criterion belongs. * @param criterion The criterion to be checked for booleanint * and booleanchar columns. * * @throws TorqueException if the database map for the criteria cannot be * retrieved. * * @deprecated */ @Deprecated private void correctBooleans(Criteria criteria, Criteria.Criterion criterion) throws TorqueException { Column column = criterion.getColumn(); TableMap tableMapFromCriteria = MapHelper.getTableMap(column, criteria, tableMap); // if no description of table available, do not modify anything if (tableMapFromCriteria != null) { String columnName = column.getColumnName(); ColumnMap columnMap = tableMapFromCriteria.getColumn(columnName); if (columnMap != null) { if ("BOOLEANINT".equals(columnMap.getTorqueType())) { replaceBooleanValues(criterion, Integer.valueOf(1), Integer.valueOf(0)); } else if ("BOOLEANCHAR".equals(columnMap.getTorqueType())) { replaceBooleanValues(criterion, "Y", "N"); } } } for (Criteria.Criterion attachedCriterion : criterion.getClauses()) { correctBooleans(criteria, attachedCriterion); } } /** * Checks all columns in the criteria to see whether * booleanchar and booleanint columns are queried with a boolean. * If yes, the query values are mapped onto values the database * does understand, i.e. 0 and 1 for booleanints and N and Y for * booleanchar columns. * * @param criteria The criteria to be checked for booleanint and booleanchar * columns. * * @throws TorqueException if the database map for the criteria cannot be * retrieved. */ public void correctBooleans(org.apache.torque.criteria.Criteria criteria) throws TorqueException { correctBooleans(criteria, criteria.getTopLevelCriterion()); } private void correctBooleans(org.apache.torque.criteria.Criteria criteria, org.apache.torque.criteria.Criterion criterion) throws TorqueException { if (criterion == null) { return; } if (criterion.isComposite()) { for (org.apache.torque.criteria.Criterion part : criterion.getParts()) { correctBooleans(criteria, part); } return; } Object possibleColumn = criterion.getLValue(); TableMap tableMapForColumn = MapHelper.getTableMap(possibleColumn, criteria, tableMap); // if no description of table available, do not modify anything if (tableMapForColumn == null) { return; } String columnName = ((Column) possibleColumn).getColumnName(); ColumnMap columnMap = tableMapForColumn.getColumn(columnName); if (columnMap != null) { if ("BOOLEANINT".equals(columnMap.getTorqueType())) { replaceBooleanValues(criterion, Integer.valueOf(1), Integer.valueOf(0)); } else if ("BOOLEANCHAR".equals(columnMap.getTorqueType())) { replaceBooleanValues(criterion, "Y", "N"); } } } /** * Replaces any Boolean value in the criterion and its attached Criterions * by trueValue if the Boolean equals <code>Boolean.TRUE</code> * and falseValue if the Boolean equals <code>Boolean.FALSE</code>. * * @param criterion the criterion to replace Boolean values in. * @param trueValue the value by which Boolean.TRUE should be replaced. * @param falseValue the value by which Boolean.FALSE should be replaced. * * @deprecated */ @Deprecated private void replaceBooleanValues(Criteria.Criterion criterion, Object trueValue, Object falseValue) { // attachedCriterions also contains the criterion itself, // so no additional treatment is needed for the criterion itself. Criteria.Criterion[] attachedCriterions = criterion.getAttachedCriterion(); for (int i = 0; i < attachedCriterions.length; ++i) { Object criterionValue = attachedCriterions[i].getValue(); if (criterionValue instanceof Boolean) { Boolean booleanValue = (Boolean) criterionValue; attachedCriterions[i].setValue(Boolean.TRUE.equals(booleanValue) ? trueValue : falseValue); } } } /** * Replaces any Boolean value in the criterion and its attached Criterions * by trueValue if the Boolean equals <code>Boolean.TRUE</code> * and falseValue if the Boolean equals <code>Boolean.FALSE</code>. * * @param criterion the criterion to replace Boolean values in. * May not be a composite criterion. * @param trueValue the value by which Boolean.TRUE should be replaced. * @param falseValue the value by which Boolean.FALSE should be replaced. */ private void replaceBooleanValues(org.apache.torque.criteria.Criterion criterion, Object trueValue, Object falseValue) { Object rValue = criterion.getRValue(); if (rValue instanceof Boolean) { Boolean booleanValue = (Boolean) rValue; criterion.setRValue(Boolean.TRUE.equals(booleanValue) ? trueValue : falseValue); } Object lValue = criterion.getLValue(); if (lValue instanceof Boolean) { Boolean booleanValue = (Boolean) lValue; criterion.setLValue(Boolean.TRUE.equals(booleanValue) ? trueValue : falseValue); } } /** * Checks all columns in the criteria to see whether * booleanchar and booleanint columns are queried with a boolean. * If yes, the query values are mapped onto values the database * does understand, i.e. 0 and 1 for booleanints and N and Y for * booleanchar columns. * * @param columnValues The value to be checked for booleanint * and booleanchar columns. * @throws TorqueException if the database map for the criteria cannot be * retrieved. */ public void correctBooleans(ColumnValues columnValues) throws TorqueException { for (Map.Entry<Column, JdbcTypedValue> entry : columnValues.entrySet()) { String columnName = entry.getKey().getColumnName(); ColumnMap column = getTableMap().getColumn(columnName); if (column != null) { JdbcTypedValue columnValue = entry.getValue(); if ("BOOLEANINT".equals(column.getTorqueType())) { if (Boolean.TRUE.equals(columnValue.getValue())) { entry.setValue(new JdbcTypedValue(1, Types.INTEGER)); } else if (Boolean.FALSE.equals(columnValue.getValue())) { entry.setValue(new JdbcTypedValue(0, Types.INTEGER)); } else if (columnValue.getValue() == null) { entry.setValue(new JdbcTypedValue(null, Types.INTEGER)); } } else if ("BOOLEANCHAR".equals(column.getTorqueType())) { if (Boolean.TRUE.equals(columnValue.getValue())) { entry.setValue(new JdbcTypedValue("Y", Types.CHAR)); } else if (Boolean.FALSE.equals(columnValue.getValue())) { entry.setValue(new JdbcTypedValue("N", Types.CHAR)); } else if (columnValue.getValue() == null) { entry.setValue(new JdbcTypedValue(null, Types.CHAR)); } } } } } /** * Sets the database name in the passed criteria to the table's default, * if it is not already set. * * @param crit the criteria to set the database name in, not null. */ protected void setDbName(org.apache.torque.criteria.Criteria crit) throws TorqueException { if (crit.getDbName() == null) { crit.setDbName(getDatabaseName()); } } /** * Sets the database name in the passed criteria to the table's default, * if it is not already set. * * @param crit the criteria to set the database name in, not null. * * @deprecated Please use addSelectColumns( * org.apache.torque.criteria.Criteria). * This method will be removed in a future version of Torque. */ @Deprecated protected void setDbName(Criteria crit) throws TorqueException { if (crit.getDbName() == null) { crit.setDbName(getDatabaseName()); } } }