You are viewing a plain text version of this content. The canonical link for it is here.
Posted to torque-dev@db.apache.org by tf...@apache.org on 2010/10/28 00:52:18 UTC
svn commit: r1028130 [2/6] - in
/db/torque/torque4/branches/trunk-without-village: torque-runtime/
torque-runtime/src/main/java/org/apache/torque/map/
torque-runtime/src/main/java/org/apache/torque/oid/
torque-runtime/src/main/java/org/apache/torque/om...
Modified: db/torque/torque4/branches/trunk-without-village/torque-runtime/src/main/java/org/apache/torque/util/BasePeer.java
URL: http://svn.apache.org/viewvc/db/torque/torque4/branches/trunk-without-village/torque-runtime/src/main/java/org/apache/torque/util/BasePeer.java?rev=1028130&r1=1028129&r2=1028130&view=diff
==============================================================================
--- db/torque/torque4/branches/trunk-without-village/torque-runtime/src/main/java/org/apache/torque/util/BasePeer.java (original)
+++ db/torque/torque4/branches/trunk-without-village/torque-runtime/src/main/java/org/apache/torque/util/BasePeer.java Wed Oct 27 22:52:15 2010
@@ -22,10 +22,11 @@ package org.apache.torque.util;
import java.io.Serializable;
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.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -39,7 +40,6 @@ 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.DB;
import org.apache.torque.map.ColumnMap;
import org.apache.torque.map.DatabaseMap;
import org.apache.torque.map.MapBuilder;
@@ -49,15 +49,7 @@ 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 com.workingdogs.village.Column;
-import com.workingdogs.village.DataSet;
-import com.workingdogs.village.DataSetException;
-import com.workingdogs.village.KeyDef;
-import com.workingdogs.village.QueryDataSet;
-import com.workingdogs.village.Record;
-import com.workingdogs.village.Schema;
-import com.workingdogs.village.TableDataSet;
+import org.apache.torque.om.mapper.RecordMapper;
/**
* This is the base class for all Peer classes in the system. Peer
@@ -113,95 +105,6 @@ public abstract class BasePeer
}
/**
- * Sets up a Schema for a table. This schema is then normally
- * used as the argument for initTableColumns().
- *
- * @param tableName The name of the table.
- * @return A Schema.
- */
- public static Schema initTableSchema(String tableName)
- {
- return initTableSchema(tableName, Torque.getDefaultDB());
- }
-
- /**
- * Sets up a Schema for a table. This schema is then normally
- * used as the argument for initTableColumns
- *
- * @param tableName The propery name for the database in the
- * configuration file.
- * @param dbName The name of the database.
- * @return A Schema.
- */
- public static Schema initTableSchema(String tableName, String dbName)
- {
- Schema schema = null;
- Connection con = null;
-
- try
- {
- con = Torque.getConnection(dbName);
- schema = new Schema().schema(con, tableName);
- }
- catch (Exception e)
- {
- log.error(e);
- throw new Error("Error in BasePeer.initTableSchema("
- + tableName
- + "): "
- + e.getMessage());
- }
- finally
- {
- Torque.closeConnection(con);
- }
- return schema;
- }
-
- /**
- * Creates a Column array for a table based on its Schema.
- *
- * @param schema A Schema object.
- * @return A Column[].
- */
- public static Column[] initTableColumns(Schema schema)
- {
- Column[] columns = null;
- try
- {
- int numberOfColumns = schema.numberOfColumns();
- columns = new Column[numberOfColumns];
- for (int i = 0; i < numberOfColumns; i++)
- {
- columns[i] = schema.column(i + 1);
- }
- }
- catch (Exception e)
- {
- log.error(e);
- throw new Error(
- "Error in BasePeer.initTableColumns(): " + e.getMessage());
- }
- return columns;
- }
-
- /**
- * Convenience method to create a String array of column names.
- *
- * @param columns A Column[].
- * @return A String[].
- */
- public static String[] initColumnNames(Column[] columns)
- {
- String[] columnNames = new String[columns.length];
- for (int i = 0; i < columns.length; i++)
- {
- columnNames[i] = columns[i].name().toUpperCase();
- }
- return columnNames;
- }
-
- /**
* Convenience method to create a String array of criteria keys.
*
* @param tableName Name of table.
@@ -368,227 +271,508 @@ public abstract class BasePeer
/**
* Method to perform deletes based on values and keys in a Criteria.
*
- * @param criteria The criteria to use.
- * @param tableName the name of the table to delete records from.
- * If set to null, the name of the table(s) can be extracted from
- * the criteria, but this can cause unexpected results.
- * @param con A Connection.
+ * @param criteria The criteria to select the records to be deleted,
+ * not null.
+ * @param tableName the name of the table to delete records from, not null.
+ * @param con The database connection for deletion, not null.
+ *
* @throws TorqueException Any exceptions caught during processing will be
* rethrown wrapped into a TorqueException.
*/
- public static void doDelete(Criteria criteria, String tableName, Connection con)
- throws TorqueException
+ public static int doDelete(
+ Criteria criteria,
+ String tableName,
+ Connection connection)
+ throws TorqueException
{
- String dbName = criteria.getDbName();
- final DatabaseMap dbMap = Torque.getDatabaseMap(dbName);
+// String dbName = criteria.getDbName();
+// final DatabaseMap dbMap = Torque.getDatabaseMap(dbName);
// This Callback adds all tables to the Table set which
// are referenced from a cascading criteria. As a result, all
// data that is referenced through foreign keys will also be
// deleted.
- SQLBuilder.TableCallback tc = new SQLBuilder.TableCallback() {
- public void process (Set<String> tables, String key, Criteria crit)
- {
- if (crit.isCascade())
- {
- // This steps thru all the columns in the database.
- TableMap[] tableMaps = dbMap.getTables();
- for (int i = 0; i < tableMaps.length; i++)
- {
- ColumnMap[] columnMaps = tableMaps[i].getColumns();
-
- for (int j = 0; j < columnMaps.length; j++)
- {
- // Only delete rows where the foreign key is
- // also a primary key. Other rows need
- // updating, but that is not implemented.
- if (columnMaps[j].isForeignKey()
- && columnMaps[j].isPrimaryKey()
- && key.equals(columnMaps[j].getRelatedName()))
- {
- tables.add(tableMaps[i].getName());
- crit.add(columnMaps[j].getFullyQualifiedName(),
- crit.getValue(key));
- }
- }
- }
- }
- }
- };
+// TODO: reimplement
+// SQLBuilder.TableCallback tc = new SQLBuilder.TableCallback() {
+// public void process (Set<String> tables, String key, Criteria crit)
+// {
+// if (crit.isCascade())
+// {
+// // This steps thru all the columns in the database.
+// TableMap[] tableMaps = dbMap.getTables();
+// for (int i = 0; i < tableMaps.length; i++)
+// {
+// ColumnMap[] columnMaps = tableMaps[i].getColumns();
+//
+// for (int j = 0; j < columnMaps.length; j++)
+// {
+// // Only delete rows where the foreign key is
+// // also a primary key. Other rows need
+// // updating, but that is not implemented.
+// if (columnMaps[j].isForeignKey()
+// && columnMaps[j].isPrimaryKey()
+// && key.equals(columnMaps[j].getRelatedName()))
+// {
+// tables.add(tableMaps[i].getName());
+// crit.add(columnMaps[j].getFullyQualifiedName(),
+// crit.getValue(key));
+// }
+// }
+// }
+// }
+// }
+// };
+
+ Query sql = createQuery(criteria);
+
+ sql.setType(Query.Type.DELETE);
+ sql.getFromClause().clear();
+ sql.getFromClause().add(new Query.FromElement(tableName, null, null));
- Set<String> tables;
- if (tableName == null)
- {
- tables = SQLBuilder.getTableSet(criteria, tc);
- }
- else
+ PreparedStatement preparedStatement = null;
+ try
{
- tables = new HashSet<String>(1);
- tables.add(tableName);
- }
+ preparedStatement = connection.prepareStatement(sql.toString());
+ long startTime = System.currentTimeMillis();
+ log.debug("Executing delete " + sql.toString());
- try
+ int affectedRows = preparedStatement.executeUpdate();
+ long queryEndTime = System.currentTimeMillis();
+ log.trace("delete took " + (queryEndTime - startTime)
+ + " milliseconds");
+
+ preparedStatement.close();
+ preparedStatement = null;
+ return affectedRows;
+ }
+ catch (SQLException e)
{
- processTables(criteria, tables, con, new ProcessCallback() {
- public void process(String table, String dbName, Record rec)
- throws Exception
- {
- rec.markToBeDeleted();
- rec.save();
- }
- });
+ throw new TorqueException(e);
}
- catch (Exception e)
+ finally
{
- throwTorqueException(e);
+ if (preparedStatement != null)
+ {
+ try
+ {
+ preparedStatement.close();
+ }
+ catch (SQLException e)
+ {
+ log.warn("error closing prepared statement", e);
+ }
+ }
}
}
/**
- * Method to perform inserts based on values and keys in a
- * Criteria.
- * <p>
- * If the primary key is auto incremented the data in Criteria
- * will be inserted and the auto increment value will be returned.
+// * Method to perform inserts based on values and keys in a
+// * Criteria.
+// * <p>
+// * If the primary key is auto incremented the data in Criteria
+// * will be inserted and the auto increment value will be returned.
+// * <p>
+// * If the primary key is included in Criteria then that value will
+// * be used to insert the row.
+// * <p>
+// * If no primary key is included in Criteria then we will try to
+// * figure out the primary key from the database map and insert the
+// * row with the next available id using util.db.IDBroker.
+// * <p>
+// * If no primary key is defined for the table the values will be
+// * inserted as specified in Criteria and -1 will be returned.
+// *
+// * @param criteria Object containing values to insert.
+// * @return An Object which is the id of the row that was inserted
+// * (if the table has a primary key) or null (if the table does not
+// * have a primary key).
+// * @throws TorqueException Any exceptions caught during processing will be
+// * rethrown wrapped into a TorqueException.
+// */
+// public static ObjectKey doInsert(Criteria criteria) throws TorqueException
+// {
+// Connection connection = null;
+// try
+// {
+// connection = Transaction.beginOptional(
+// criteria.getDbName(),
+// criteria.isUseTransaction());
+// ObjectKey id = doInsert(criteria, connection);
+// Transaction.commit(connection);
+// connection = null;
+// return id;
+// }
+// finally
+// {
+// if (connection != null)
+// {
+// Transaction.safeRollback(connection);
+// }
+// }
+// }
+//
+// /**
+// * Method to perform inserts based on values and keys in a
+// * Criteria.
+// * <p>
+// * If the primary key is auto incremented the data in Criteria
+// * will be inserted and the auto increment value will be returned.
+// * <p>
+// * If the primary key is included in Criteria then that value will
+// * be used to insert the row.
+// * <p>
+// * If no primary key is included in Criteria then we will try to
+// * figure out the primary key from the database map and insert the
+// * row with the next available id using util.db.IDBroker.
+// * <p>
+// * If no primary key is defined for the table the values will be
+// * inserted as specified in Criteria and null will be returned.
+// *
+// * @param criteria Object containing values to insert.
+// * @param con A Connection.
+// * @return An Object which is the id of the row that was inserted
+// * (if the table has a primary key) or null (if the table does not
+// * have a primary key).
+// * @throws TorqueException Any exceptions caught during processing will be
+// * rethrown wrapped into a TorqueException.
+// */
+// public static ObjectKey doInsert(Criteria criteria, Connection con)
+// throws TorqueException
+// {
+// SimpleKey id = null;
+//
+// // Get the table name and method for determining the primary
+// // key value.
+// String table = null;
+// Iterator<?> keys = criteria.keySet().iterator();
+// if (keys.hasNext())
+// {
+// table = criteria.getTableName((String) keys.next());
+// }
+// else
+// {
+// throw new TorqueException("Database insert attempted without "
+// + "anything specified to insert");
+// }
+//
+// String dbName = criteria.getDbName();
+// Database database = Torque.getDatabase(dbName);
+// DatabaseMap dbMap = database.getDatabaseMap();
+// TableMap tableMap = dbMap.getTable(table);
+// Object keyInfo = tableMap.getPrimaryKeyMethodInfo();
+// IdGenerator keyGen
+// = database.getIdGenerator(tableMap.getPrimaryKeyMethod());
+//
+// ColumnMap pk = getPrimaryKey(criteria);
+//
+// // If the keyMethod is SEQUENCE or IDBROKERTABLE, get the id
+// // before the insert.
+// if (keyGen != null && keyGen.isPriorToInsert())
+// {
+// // pk will be null if there is no primary key defined for the table
+// // we're inserting into.
+// if (pk != null && !criteria.containsKey(pk.getFullyQualifiedName()))
+// {
+// id = getId(pk, keyGen, con, keyInfo);
+// criteria.add(pk.getFullyQualifiedName(), id.getValue());
+// }
+// }
+//
+// List<String> columnNames = new ArrayList<String>();
+// List<Object> replacementObjects = new ArrayList<Object>();
+// for (Object updateValueObject : criteria.entrySet())
+// {
+// Map.Entry<?, ?> updateValue = (Map.Entry<?, ?>) updateValueObject;
+// String columnName = updateValue.getKey().toString();
+// if (columnName.lastIndexOf(".") != -1)
+// {
+// columnName = columnName.substring(
+// columnName.lastIndexOf(".") + 1);
+// }
+// columnNames.add(columnName);
+// replacementObjects.add(
+// ((Criteria.Criterion) updateValue.getValue()).getValue());
+// }
+//
+// StringBuilder query = new StringBuilder("INSERT INTO ")
+// .append(table)
+// .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 = con.prepareStatement(query.toString());
+// int position = 1;
+// for (Object replacementObject : replacementObjects)
+// {
+// preparedStatement.setObject(position, replacementObject);
+// 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 new TorqueException(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())
+// {
+// id = getId(pk, keyGen, con, keyInfo);
+// }
+//
+// return id;
+// }
+
+ /**
+ * Inserts a record into a database table.
* <p>
- * If the primary key is included in Criteria then that value will
+ * If the primary key is included in Criteria, then that value will
* be used to insert the row.
* <p>
- * If no primary key is included in Criteria then we will try to
- * figure out the primary key from the database map and insert the
- * row with the next available id using util.db.IDBroker.
+ * 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 primary key is defined for the table the values will be
- * inserted as specified in Criteria and -1 will be returned.
+ * 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 criteria Object containing values to insert.
- * @return An Object which is the id of the row that was inserted
- * (if the table has a primary key) or null (if the table does not
- * have a primary key).
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
+ * @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 static ObjectKey doInsert(Criteria criteria) throws TorqueException
+ public static ObjectKey doInsert(ColumnValues insertValues)
+ throws TorqueException
{
- Connection con = null;
- ObjectKey id = null;
-
+ String databaseName;
+ {
+ TableMap table = insertValues.getTable();
+ if (table == null)
+ {
+ log.debug("doUpdate(): no Table set in updateValues, "
+ + "using default database");
+ databaseName = Torque.getDefaultDB();
+ }
+ else
+ {
+ databaseName = table.getDatabaseMap().getName();
+ }
+ }
+ Connection connection = null;
try
{
- con = Transaction.beginOptional(
- criteria.getDbName(),
- criteria.isUseTransaction());
- id = doInsert(criteria, con);
- Transaction.commit(con);
+ connection = Transaction.begin(databaseName);
+ ObjectKey id = doInsert(insertValues, connection);
+ Transaction.commit(connection);
+ connection = null;
+ return id;
}
- catch (TorqueException e)
+ finally
{
- Transaction.safeRollback(con);
- throw e;
+ if (connection != null)
+ {
+ Transaction.safeRollback(connection);
+ }
}
-
- return id;
}
/**
- * Method to perform inserts based on values and keys in a
- * Criteria.
+ * Inserts a record into a database table.
* <p>
- * If the primary key is auto incremented the data in Criteria
- * will be inserted and the auto increment value will be returned.
- * <p>
- * If the primary key is included in Criteria then that value will
+ * If the primary key is included in Criteria, then that value will
* be used to insert the row.
* <p>
- * If no primary key is included in Criteria then we will try to
- * figure out the primary key from the database map and insert the
- * row with the next available id using util.db.IDBroker.
+ * 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 primary key is defined for the table the values will be
- * inserted as specified in Criteria and null will be returned.
- *
- * @param criteria Object containing values to insert.
- * @param con A Connection.
- * @return An Object which is the id of the row that was inserted
- * (if the table has a primary key) or null (if the table does not
- * have a primary key).
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- public static ObjectKey doInsert(Criteria criteria, Connection con)
- throws TorqueException
+ * 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 static ObjectKey doInsert(
+ ColumnValues insertValues,
+ Connection connection)
+ throws TorqueException
{
- SimpleKey id = null;
-
- // Get the table name and method for determining the primary
- // key value.
- String table = null;
- Iterator<?> keys = criteria.keySet().iterator();
- if (keys.hasNext())
- {
- table = criteria.getTableName((String) keys.next());
- }
- else
- {
- throw new TorqueException("Database insert attempted without "
- + "anything specified to insert");
- }
-
- String dbName = criteria.getDbName();
- Database database = Torque.getDatabase(dbName);
- DatabaseMap dbMap = database.getDatabaseMap();
- TableMap tableMap = dbMap.getTable(table);
+ TableMap tableMap = insertValues.getTable();
+ DatabaseMap dbMap = tableMap.getDatabaseMap();
+ Database database = Torque.getDatabase(dbMap.getName());
Object keyInfo = tableMap.getPrimaryKeyMethodInfo();
IdGenerator keyGen
= database.getIdGenerator(tableMap.getPrimaryKeyMethod());
- ColumnMap pk = getPrimaryKey(criteria);
-
- // If the keyMethod is SEQUENCE or IDBROKERTABLE, get the id
- // before the insert.
- if (keyGen != null && keyGen.isPriorToInsert())
+ SimpleKey id = null;
+ // can currently generate only single column pks, therefore a single
+ // columnMap is ok
+ ColumnMap primaryKey = null;
+ if (keyGen != null)
{
- // pk will be null if there is no primary key defined for the table
- // we're inserting into.
- if (pk != null && !criteria.containsKey(pk.getFullyQualifiedName()))
+ // fail on multiple pks
+ primaryKey = tableMap.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.getFullyQualifiedName()))
{
- id = getId(pk, keyGen, con, keyInfo);
- criteria.add(pk.getFullyQualifiedName(), id);
+ id = getId(primaryKey, keyGen, connection, keyInfo);
+ insertValues.put(
+ primaryKey.getFullyQualifiedName(),
+ new JdbcTypedValue(id.getValue(), id.getJdbcType()));
}
}
- // Use Village to perform the insert.
- TableDataSet tds = null;
- try
+ List<String> columnNames = new ArrayList<String>();
+ List<JdbcTypedValue> replacementObjects
+ = new ArrayList<JdbcTypedValue>();
+ for (Map.Entry<String, JdbcTypedValue> columnValue
+ : insertValues.entrySet())
{
- String tableName = SQLBuilder.getFullTableName(table, dbName);
- tds = new TableDataSet(con, tableName);
- Record rec = tds.addRecord();
- // not the fully qualified name, insertOrUpdateRecord wants to use table as an index...
- BasePeer.insertOrUpdateRecord(rec, table, dbName, criteria);
+ String columnName = columnValue.getKey();
+ if (columnName.lastIndexOf(".") != -1)
+ {
+ columnName = columnName.substring(
+ columnName.lastIndexOf(".") + 1);
+ }
+ columnNames.add(columnName);
+ JdbcTypedValue value = columnValue.getValue();
+ replacementObjects.add(value);
}
- catch (DataSetException e)
+
+ StringBuilder query = new StringBuilder("INSERT INTO ")
+ .append(tableMap.getName())
+ .append("(")
+ .append(StringUtils.join(columnNames, ","))
+ .append(") VALUES (");
+ for (int i = 0; i < columnNames.size(); ++i)
{
- throwTorqueException(e);
+ if (i != 0)
+ {
+ query.append(",");
+ }
+ query.append("?");
}
- catch (SQLException e)
+ query.append(")");
+
+ PreparedStatement preparedStatement = null;
+ try
{
- throwTorqueException(e);
+ 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 (TorqueException e)
+ catch (SQLException e)
{
- throwTorqueException(e);
+ throw new TorqueException(e);
}
finally
{
- VillageUtils.close(tds);
+ 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())
{
- id = getId(pk, keyGen, con, keyInfo);
+ id = getId(primaryKey, keyGen, connection, keyInfo);
}
return id;
@@ -633,66 +817,6 @@ public abstract class BasePeer
}
/**
- * Grouping of code used in both doInsert() and doUpdate()
- * methods. Sets up a Record for saving.
- *
- * @param rec A Record.
- * @param table Name of table.
- * @param criteria A Criteria.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- private static void insertOrUpdateRecord(
- Record rec,
- String table,
- String dbName,
- Criteria criteria)
- throws TorqueException
- {
- DatabaseMap dbMap = Torque.getDatabaseMap(dbName);
-
- ColumnMap[] columnMaps = dbMap.getTable(table).getColumns();
- boolean shouldSave = false;
- for (int j = 0; j < columnMaps.length; j++)
- {
- ColumnMap colMap = columnMaps[j];
- String colName = colMap.getColumnName();
- String key = new StringBuffer(colMap.getTableName())
- .append('.')
- .append(colName)
- .toString();
- if (criteria.containsKey(key))
- {
- try
- {
- VillageUtils.setVillageValue(criteria, key, rec, colName);
- shouldSave = true;
- }
- catch (Exception e)
- {
- throwTorqueException(e);
- }
- }
- }
-
- if (shouldSave)
- {
- try
- {
- rec.save();
- }
- catch (Exception e)
- {
- throwTorqueException(e);
- }
- }
- else
- {
- throw new TorqueException("No changes to save");
- }
- }
-
- /**
* Method to create an SQL query for display only based on values in a
* Criteria.
*
@@ -742,452 +866,664 @@ public abstract class BasePeer
}
/**
- * Returns all results.
+ * Selects rows from a database an maps them to objects.
*
- * @param criteria A Criteria.
- * @return List of Record objects.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- public static List<Record> doSelectVillageRecords(
- Criteria criteria)
+ * @param criteria A Criteria specifying the records to select, not null.
+ * @param mapper The mapper creating the objects from the resultSet,
+ * not null.
+ * @param defaultTableMap The table map used for the
+ * unqualified columns in the query, not null.
+ *
+ * @return The results of the query, not null.
+ *
+ * @throws TorqueException if querying the database fails.
+ */
+ public static <T> List<T> doSelect(
+ Criteria criteria,
+ RecordMapper<T> mapper,
+ TableMap defaultTableMap)
throws TorqueException
{
- Connection con = null;
- List<Record> results = null;
-
+ Connection connection = null;
try
{
- con = Transaction.beginOptional(
+ connection = Transaction.beginOptional(
criteria.getDbName(),
criteria.isUseTransaction());
- results = doSelectVillageRecords(criteria, con);
- Transaction.commit(con);
+
+ List<T> result = doSelect(
+ criteria,
+ mapper,
+ defaultTableMap,
+ connection);
+
+ Transaction.commit(connection);
+ connection = null;
+ return result;
}
- catch (TorqueException e)
+ finally
{
- Transaction.safeRollback(con);
- throw e;
+ if (connection != null)
+ {
+ Transaction.safeRollback(connection);
+ }
}
- return results;
}
/**
- * Returns all results.
+ * Selects rows from a database an maps them to objects.
*
- * @param criteria A Criteria.
- * @param con A Connection.
- * @return List of Record objects.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
+ * @param query the sql query to execute, not null.
+ * @param mapper The mapper creating the objects from the resultSet,
+ * not null.
+ * @param defaultTableMap The table map used for the
+ * unqualified columns in the query, not null.
+ * @param dbName The name of the database to create the connection for,
+ * or null for the default SDB.
+ *
+ * @return The results of the query, not null.
+ *
+ * @throws TorqueException if querying the database fails.
*/
- public static List<Record> doSelectVillageRecords(
- Criteria criteria, Connection con)
+ public static <T> List<T> doSelect(
+ String query,
+ RecordMapper<T> mapper,
+ TableMap defaultTableMap,
+ String dbName)
throws TorqueException
{
- Query query = createQuery(criteria);
- DB dbadapter = Torque.getDB(criteria.getDbName());
-
- // Call Village depending on the capabilities of the DB
- return executeQuery(query.toString(),
- dbadapter.supportsNativeOffset() ? 0 : criteria.getOffset(),
- dbadapter.supportsNativeLimit() ? -1 : criteria.getLimit(),
- criteria.isSingleRecord(),
- con);
+ if (dbName == null)
+ {
+ dbName = Torque.getDefaultDB();
+ }
+ Connection connection = null;
+ try
+ {
+ connection = Transaction.beginOptional(
+ dbName,
+ true);
+
+ List<T> result = doSelect(
+ query,
+ mapper,
+ defaultTableMap,
+ connection);
+
+ Transaction.commit(connection);
+ connection = null;
+ return result;
+ }
+ finally
+ {
+ if (connection != null)
+ {
+ Transaction.safeRollback(connection);
+ }
+ }
}
/**
- * Utility method which executes a given sql statement. This
- * method should be used for select statements only. Use
- * executeStatement for update, insert, and delete operations.
+ * Selects rows from a database an maps them to objects.
*
- * @param queryString A String with the sql statement to execute.
- * @return List of Record objects.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- public static List<Record> executeQuery(String queryString) throws TorqueException
- {
- return executeQuery(queryString, Torque.getDefaultDB(), false);
- }
-
- /**
- * Utility method which executes a given sql statement. This
- * method should be used for select statements only. Use
- * executeStatement for update, insert, and delete operations.
+ * @param criteria A Criteria specifying the records to select, not null.
+ * @param mapper The mapper creating the objects from the resultSet,
+ * not null.
+ * @param defaultTableMap The table map used for the
+ * unqualified columns in the query, not null.
+ * @param connection the database connection, not null.
*
- * @param queryString A String with the sql statement to execute.
- * @param dbName The database to connect to.
- * @return List of Record objects.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- public static List<Record> executeQuery(String queryString, String dbName)
- throws TorqueException
- {
- return executeQuery(queryString, dbName, false);
- }
-
- /**
- * Method for performing a SELECT. Returns all results.
+ * @return The results of the query, not null.
*
- * @param queryString A String with the sql statement to execute.
- * @param dbName The database to connect to.
- * @param singleRecord Whether or not we want to select only a
- * single record.
- * @return List of Record objects.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
+ * @throws TorqueException if querying the database fails.
*/
- public static List<Record> executeQuery(
- String queryString,
- String dbName,
- boolean singleRecord)
- throws TorqueException
+ public static <T> List<T> doSelect(
+ Criteria criteria,
+ RecordMapper<T> mapper,
+ TableMap defaultTableMap,
+ Connection connection)
+ throws TorqueException
{
- return executeQuery(queryString, 0, -1, dbName, singleRecord);
- }
-
- /**
- * Method for performing a SELECT. Returns all results.
- *
- * @param queryString A String with the sql statement to execute.
- * @param singleRecord Whether or not we want to select only a
- * single record.
- * @param con A Connection.
- * @return List of Record objects.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- public static List<Record> executeQuery(
- String queryString,
- boolean singleRecord,
- Connection con)
- throws TorqueException
- {
- return executeQuery(queryString, 0, -1, singleRecord, con);
- }
-
- /**
- * Method for performing a SELECT.
- *
- * @param queryString A String with the sql statement to execute.
- * @param start The first row to return.
- * @param numberOfResults The number of rows to return.
- * @param dbName The database to connect to.
- * @param singleRecord Whether or not we want to select only a
- * single record.
- * @return List of Record objects.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- public static List<Record> executeQuery(
- String queryString,
- int start,
- int numberOfResults,
- String dbName,
- boolean singleRecord)
- throws TorqueException
- {
- Connection con = null;
- List<Record> results = null;
- try
- {
- con = Torque.getConnection(dbName);
- // execute the query
- results = executeQuery(
- queryString,
- start,
- numberOfResults,
- singleRecord,
- con);
- }
- finally
+ if (connection == null)
{
- Torque.closeConnection(con);
+ throw new NullPointerException("connection is null");
}
- return results;
- }
- /**
- * Method for performing a SELECT. Returns all results.
- *
- * @param queryString A String with the sql statement to execute.
- * @param start The first row to return.
- * @param numberOfResults The number of rows to return.
- * @param singleRecord Whether or not we want to select only a
- * single record.
- * @param con A Connection.
- * @return List of Record objects.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- public static List<Record> executeQuery(
- String queryString,
- int start,
- int numberOfResults,
- boolean singleRecord,
- Connection con)
- throws TorqueException
- {
- QueryDataSet qds = null;
- List<Record> results = Collections.emptyList();
+ correctBooleans(criteria, defaultTableMap);
+
+ Database database = Torque.getDatabase(criteria.getDbName());
+ String query = createQuery(criteria).toString();
+
+ Statement statement = null;
+ ResultSet resultSet = null;
try
{
- // execute the query
+ statement = connection.createStatement();
long startTime = System.currentTimeMillis();
- qds = new QueryDataSet(con, queryString);
- if (log.isDebugEnabled())
+ log.debug("Executing query " + query);
+
+ resultSet = statement.executeQuery(query.toString());
+ long queryEndTime = System.currentTimeMillis();
+ log.trace("query took " + (queryEndTime - startTime)
+ + " milliseconds");
+
+ int offset;
+ if (database.getAdapter().supportsNativeOffset())
{
- log.debug("Elapsed time="
- + (System.currentTimeMillis() - startTime) + " ms");
+ offset = 0; //database takes care of offset
}
- results = getSelectResults(
- qds, start, numberOfResults, singleRecord);
- }
- catch (DataSetException e)
- {
- throwTorqueException(e);
+ else
+ {
+ offset = criteria.getOffset();
+ }
+
+ int 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<T> result = new ArrayList<T>();
+ int rowNumber = 0;
+ while (resultSet.next())
+ {
+ if (rowNumber < offset)
+ {
+ rowNumber++;
+ continue;
+ }
+ if (limit >= 0 && rowNumber >= limit)
+ {
+ break;
+ }
+
+ T rowResult = mapper.processRow(resultSet, 0);
+ 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)
{
- throwTorqueException(e);
+ throw new TorqueException(e);
}
finally
{
- VillageUtils.close(qds);
+ 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 results;
}
/**
- * Returns all records in a QueryDataSet as a List of Record
- * objects. Used for functionality like util.LargeSelect.
+ * Selects rows from a database an maps them to objects.
*
- * @see #getSelectResults(QueryDataSet, int, int, boolean)
- * @param qds the QueryDataSet
- * @return a List of Record objects
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- public static List<Record> getSelectResults(QueryDataSet qds)
- throws TorqueException
- {
- return getSelectResults(qds, 0, -1, false);
- }
-
- /**
- * Returns all records in a QueryDataSet as a List of Record
- * objects. Used for functionality like util.LargeSelect.
+ * @param query the SQL Query to execute, not null.
+ * @param mapper The mapper creating the objects from the resultSet,
+ * not null.
+ * @param defaultTableMap The table map used for the
+ * unqualified columns in the query, not null.
+ * @param connection the database connection, not null.
*
- * @see #getSelectResults(QueryDataSet, int, int, boolean)
- * @param qds the QueryDataSet
- * @param singleRecord
- * @return a List of Record objects
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- public static List<Record> getSelectResults(QueryDataSet qds, boolean singleRecord)
- throws TorqueException
- {
- return getSelectResults(qds, 0, -1, singleRecord);
- }
-
- /**
- * Returns numberOfResults records in a QueryDataSet as a List
- * of Record objects. Starting at record 0. Used for
- * functionality like util.LargeSelect.
+ * @return The results of the query, not null.
*
- * @see #getSelectResults(QueryDataSet, int, int, boolean)
- * @param qds the QueryDataSet
- * @param numberOfResults
- * @param singleRecord
- * @return a List of Record objects
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
+ * @throws TorqueException if querying the database fails.
*/
- public static List<Record> getSelectResults(
- QueryDataSet qds,
- int numberOfResults,
- boolean singleRecord)
- throws TorqueException
+ public static <T> List<T> doSelect(
+ String query,
+ RecordMapper<T> mapper,
+ TableMap defaultTableMap,
+ Connection connection)
+ throws TorqueException
{
- List<Record> results = null;
- if (numberOfResults != 0)
+ if (connection == null)
{
- results = getSelectResults(qds, 0, numberOfResults, singleRecord);
+ throw new NullPointerException("connection is null");
}
- return results;
- }
- /**
- * Returns numberOfResults records in a QueryDataSet as a List
- * of Record objects. Starting at record start. Used for
- * functionality like util.LargeSelect.
- *
- * @param qds The <code>QueryDataSet</code> to extract results
- * from.
- * @param start The index from which to start retrieving
- * <code>Record</code> objects from the data set.
- * @param numberOfResults The number of results to return (or
- * <code> -1</code> for all results).
- * @param singleRecord Whether or not we want to select only a
- * single record.
- * @return A <code>List</code> of <code>Record</code> objects.
- * @exception TorqueException If any <code>Exception</code> occurs.
- */
- public static List<Record> getSelectResults(
- QueryDataSet qds,
- int start,
- int numberOfResults,
- boolean singleRecord)
- throws TorqueException
- {
- List<Record> results = null;
+ List<T> result = new ArrayList<T>();
+ Statement statement = null;
+ ResultSet resultSet = null;
try
{
- if (numberOfResults < 0)
- {
- results = new ArrayList<Record>();
- qds.fetchRecords();
- }
- else
- {
- results = new ArrayList<Record>(numberOfResults);
- qds.fetchRecords(start, numberOfResults);
- }
-
- int startRecord = 0;
-
- //Offset the correct number of records
- if (start > 0 && numberOfResults <= 0)
- {
- startRecord = start;
- }
+ statement = connection.createStatement();
+ long startTime = System.currentTimeMillis();
+ log.debug("Executing query " + query);
- // Return a List of Record objects.
- for (int i = startRecord; i < qds.size(); i++)
- {
- Record rec = qds.getRecord(i);
- results.add(rec);
- }
+ resultSet = statement.executeQuery(query.toString());
+ long queryEndTime = System.currentTimeMillis();
+ log.trace("query took " + (queryEndTime - startTime)
+ + " milliseconds");
- if (results.size() > 1 && singleRecord)
+ while (resultSet.next())
{
- handleMultipleRecords(qds);
+ T rowResult = mapper.processRow(resultSet, 0);
+ result.add(rowResult);
}
+ long mappingEndTime = System.currentTimeMillis();
+ log.trace("mapping took " + (mappingEndTime - queryEndTime)
+ + " milliseconds");
}
- catch (Exception e)
+ catch (SQLException e)
{
- throwTorqueException(e);
+ throw new TorqueException(e);
}
- return results;
- }
-
- /**
- * Helper method which returns the primary key contained
- * in the given Criteria object.
- *
- * @param criteria A Criteria.
- * @return ColumnMap if the Criteria object contains a primary
- * key, or null if it doesn't.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- private static ColumnMap getPrimaryKey(Criteria criteria)
- throws TorqueException
- {
- // Assume all the keys are for the same table.
- String key = (String) criteria.keys().nextElement();
-
- String table = criteria.getTableName(key);
- ColumnMap pk = null;
-
- if (!table.equals(""))
+ finally
{
- DatabaseMap dbMap = Torque.getDatabaseMap(criteria.getDbName());
- if (dbMap == null)
- {
- throw new TorqueException("dbMap is null");
- }
- if (dbMap.getTable(table) == null)
+ if (resultSet != null)
{
- throw new TorqueException("dbMap.getTable() is null");
+ try
+ {
+ resultSet.close();
+ }
+ catch (SQLException e)
+ {
+ log.warn("error closing resultSet", e);
+ }
}
-
- ColumnMap[] columns = dbMap.getTable(table).getColumns();
-
- for (int i = 0; i < columns.length; i++)
+ if (statement != null)
{
- if (columns[i].isPrimaryKey())
+ try
{
- pk = columns[i];
- break;
+ statement.close();
+ }
+ catch (SQLException e)
+ {
+ log.warn("error closing statement", e);
}
}
}
- return pk;
+ return result;
}
+// /**
+// * Helper method which returns the primary key contained
+// * in the given Criteria object.
+// *
+// * @param criteria A Criteria.
+// * @return ColumnMap if the Criteria object contains a primary
+// * key, or null if it doesn't.
+// * @throws TorqueException Any exceptions caught during processing will be
+// * rethrown wrapped into a TorqueException.
+// */
+// private static ColumnMap getPrimaryKey(Criteria criteria)
+// throws TorqueException
+// {
+// // Assume all the keys are for the same table.
+// String key = (String) criteria.keys().nextElement();
+//
+// String table = criteria.getTableName(key);
+// ColumnMap pk = null;
+//
+// if (!table.equals(""))
+// {
+// DatabaseMap dbMap = Torque.getDatabaseMap(criteria.getDbName());
+// if (dbMap == null)
+// {
+// throw new TorqueException("dbMap is null");
+// }
+// if (dbMap.getTable(table) == null)
+// {
+// throw new TorqueException("dbMap.getTable() is null");
+// }
+//
+// ColumnMap[] columns = dbMap.getTable(table).getColumns();
+//
+// for (int i = 0; i < columns.length; i++)
+// {
+// if (columns[i].isPrimaryKey())
+// {
+// pk = columns[i];
+// break;
+// }
+// }
+// }
+// return pk;
+// }
+//
+// /**
+// * Convenience method used to update rows in the DB. Checks if a
+// * <i>single</i> int primary key is specified in the Criteria
+// * object and uses it to perform the udpate. If no primary key is
+// * specified an Exception will be thrown.
+// * <p>
+// * Use this method for performing an update of the kind:
+// * <p>
+// * "WHERE primary_key_id = an int"
+// * <p>
+// * To perform an update with non-primary key fields in the WHERE
+// * clause use doUpdate(criteria, criteria).
+// *
+// * @param updateValues A Criteria object containing values used in
+// * set clause.
+// *
+// * @return the number of affected rows.
+// *
+// * @throws TorqueException Any exceptions caught during processing will be
+// * rethrown wrapped into a TorqueException.
+// */
+// public static int doUpdate(Criteria updateValues) throws TorqueException
+// {
+// Connection connection = null;
+// try
+// {
+// connection = Transaction.beginOptional(
+// updateValues.getDbName(),
+// updateValues.isUseTransaction());
+// 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> int primary key is specified in the Criteria
+// * object and uses it to perform the udpate. If no primary key is
+// * specified an Exception will be thrown.
+// * <p>
+// * Use this method for performing an update of the kind:
+// * <p>
+// * "WHERE primary_key_id = an int"
+// * <p>
+// * To perform an update with non-primary key fields in the WHERE
+// * clause use doUpdate(criteria, criteria).
+// *
+// * @param updateValues A Criteria object containing values used in
+// * set clause.
+// * @param con A Connection.
+// *
+// * @return the number of affected rows.
+// *
+// * @throws TorqueException Any exceptions caught during processing will be
+// * rethrown wrapped into a TorqueException.
+// */
+// public static int doUpdate(Criteria updateValues, Connection con)
+// throws TorqueException
+// {
+// ColumnMap pk = getPrimaryKey(updateValues);
+// Criteria selectCriteria = null;
+//
+// if (pk != null && updateValues.containsKey(pk.getFullyQualifiedName()))
+// {
+// selectCriteria = new Criteria(2);
+// selectCriteria.put(pk.getFullyQualifiedName(),
+// updateValues.remove(pk.getFullyQualifiedName()));
+// }
+// else
+// {
+// throw new TorqueException("No PK specified for database update");
+// }
+//
+// return doUpdate(selectCriteria, updateValues, con);
+// }
+//
+// /**
+// * 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(map keys) should be set to which
+// * values.
+// * @param connection the database connection to use, not null.
+// *
+// * @return the number of affected rows.
+// *
+// * @throws TorqueException if updating fails.
+// */
+// public static void doUpdate(
+// Criteria selectCriteria,
+// Criteria updateValues)
+// throws TorqueException
+// {
+// Connection con = null;
+// try
+// {
+// con = Transaction.beginOptional(
+// selectCriteria.getDbName(),
+// selectCriteria.isUseTransaction());
+// doUpdate(selectCriteria, updateValues, con);
+// Transaction.commit(con);
+// }
+// catch (TorqueException e)
+// {
+// Transaction.safeRollback(con);
+// throw 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(map keys) should be set to which
+// * values.
+// * @param connection the database connection to use, not null.
+// *
+// * @return the number of affected rows.
+// *
+// * @throws TorqueException if updating fails.
+// */
+// public static int doUpdate(
+// Criteria criteria,
+// Criteria updateValues,
+// Connection connection)
+// throws TorqueException
+// {
+// Query sql = createQuery(criteria);
+// sql.setType(Query.Type.UPDATE);
+//
+// // ignore select columns in criteria
+// sql.getSelectClause().clear();
+// List<Object> replacementObjects = new ArrayList<Object>();
+// for (Object updateValueObject : updateValues.entrySet())
+// {
+// Map.Entry<?, ?> updateValue = (Map.Entry<?, ?>) updateValueObject;
+// String columnName = updateValue.getKey().toString();
+// if (columnName.lastIndexOf(".") != -1)
+// {
+// columnName = columnName.substring(
+// columnName.lastIndexOf(".") + 1);
+// }
+// sql.getSelectClause().add(columnName);
+// replacementObjects.add(
+// ((Criteria.Criterion) updateValue.getValue()).getValue());
+// }
+//
+// PreparedStatement preparedStatement = null;
+// try
+// {
+// preparedStatement = connection.prepareStatement(sql.toString());
+// int position = 1;
+// for (Object replacementObject : replacementObjects)
+// {
+// preparedStatement.setObject(position, replacementObject);
+// position++;
+// }
+// long startTime = System.currentTimeMillis();
+// log.debug("Executing update " + sql.toString()
+// + " using parameters " + replacementObjects);
+//
+// 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 new TorqueException(e);
+// }
+// finally
+// {
+// if (preparedStatement != null)
+// {
+// try
+// {
+// preparedStatement.close();
+// }
+// catch (SQLException e)
+// {
+// log.warn("error closing prepared statement", e);
+// }
+// }
+// }
+// }
+
+
/**
* Convenience method used to update rows in the DB. Checks if a
- * <i>single</i> int primary key is specified in the Criteria
- * object and uses it to perform the udpate. If no primary key is
- * specified an Exception will be thrown.
+ * <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 = an int"
+ * "WHERE primary_key_id = someValue"
* <p>
- * To perform an update with non-primary key fields in the WHERE
- * clause use doUpdate(criteria, criteria).
+ * 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.
*
- * @param updateValues A Criteria object containing values used in
- * set clause.
* @throws TorqueException Any exceptions caught during processing will be
* rethrown wrapped into a TorqueException.
*/
- public static void doUpdate(Criteria updateValues) throws TorqueException
+ public static int doUpdate(ColumnValues updateValues)
+ throws TorqueException
{
- Connection con = null;
+ String databaseName;
+ {
+ TableMap table = updateValues.getTable();
+ if (table == null)
+ {
+ log.debug("doUpdate(): no Table set in updateValues, "
+ + "using default database");
+ databaseName = Torque.getDefaultDB();
+ }
+ else
+ {
+ databaseName = table.getDatabaseMap().getName();
+ }
+ }
+ Connection connection = null;
try
{
- con = Transaction.beginOptional(
- updateValues.getDbName(),
- updateValues.isUseTransaction());
- doUpdate(updateValues, con);
- Transaction.commit(con);
+ connection = Transaction.begin(databaseName);
+ int result = doUpdate(updateValues, connection);
+ Transaction.commit(connection);
+ connection = null;
+ return result;
}
- catch (TorqueException e)
+ finally
{
- Transaction.safeRollback(con);
- throw e;
+ if (connection != null)
+ {
+ Transaction.safeRollback(connection);
+ }
}
}
/**
* Convenience method used to update rows in the DB. Checks if a
- * <i>single</i> int primary key is specified in the Criteria
- * object and uses it to perform the udpate. If no primary key is
- * specified an Exception will be thrown.
+ * <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 = an int"
+ * "WHERE primary_key_id = someValue"
* <p>
- * To perform an update with non-primary key fields in the WHERE
- * clause use doUpdate(criteria, criteria).
+ * 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.
+ *
+ * @param updateValues A map keyed by the column names
+ * containing the column's values in its values.
+ * @param connection the database connection to use.
*
- * @param updateValues A Criteria object containing values used in
- * set clause.
- * @param con A Connection.
* @throws TorqueException Any exceptions caught during processing will be
* rethrown wrapped into a TorqueException.
*/
- public static void doUpdate(Criteria updateValues, Connection con)
- throws TorqueException
+ public static int doUpdate(
+ ColumnValues updateValues,
+ Connection connection)
+ throws TorqueException
{
- ColumnMap pk = getPrimaryKey(updateValues);
+ TableMap table = updateValues.getTable();
+ ColumnMap pk = table.getPrimaryKey();
Criteria selectCriteria = null;
if (pk != null && updateValues.containsKey(pk.getFullyQualifiedName()))
@@ -1201,83 +1537,147 @@ public abstract class BasePeer
throw new TorqueException("No PK specified for database update");
}
- doUpdate(selectCriteria, updateValues, con);
+ return doUpdate(selectCriteria, updateValues, connection);
}
/**
- * Method used to update rows in the DB. Rows are selected based
- * on selectCriteria and updated using values in updateValues.
- * <p>
- * Use this method for performing an update of the kind:
- * <p>
- * WHERE some_column = some value AND could_have_another_column =
- * another value AND so on...
+ * 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 A Criteria object containing values used in where
- * clause.
- * @param updateValues A Criteria object containing values used in set
- * clause.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
+ * @param criteria selects which rows of which table should be updated.
+ * @param updateValues Which columns to update with which values, not null.
+ *
+ * @return the number of affected rows.
+ *
+ * @throws TorqueException if updating fails.
*/
- public static void doUpdate(Criteria selectCriteria, Criteria updateValues)
- throws TorqueException
+ public static int doUpdate(
+ Criteria selectCriteria,
+ ColumnValues updateValues)
+ throws TorqueException
{
- Connection con = null;
+ String databaseName;
+ {
+ TableMap table = updateValues.getTable();
+ if (table == null)
+ {
+ log.debug("doUpdate(): no Table set in updateValues, "
+ + "using default database");
+ databaseName = Torque.getDefaultDB();
+ }
+ else
+ {
+ databaseName = table.getDatabaseMap().getName();
+ }
+ }
+ Connection connection = null;
try
{
- con = Transaction.beginOptional(
- selectCriteria.getDbName(),
- updateValues.isUseTransaction());
- doUpdate(selectCriteria, updateValues, con);
- Transaction.commit(con);
+ connection = Transaction.begin(databaseName);
+ int result = doUpdate(selectCriteria, updateValues, connection);
+ Transaction.commit(connection);
+ connection = null;
+ return result;
}
- catch (TorqueException e)
+ finally
{
- Transaction.safeRollback(con);
- throw e;
+ if (connection != null)
+ {
+ Transaction.safeRollback(connection);
+ }
}
}
/**
- * Method used to update rows in the DB. Rows are selected based
- * on criteria and updated using values in updateValues.
- * <p>
- * Use this method for performing an update of the kind:
- * <p>
- * WHERE some_column = some value AND could_have_another_column =
- * another value AND so on.
+ * 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 A Criteria object containing values used in where
- * clause.
- * @param updateValues A Criteria object containing values used in set
- * clause.
- * @param con A Connection.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
+ * @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 static void doUpdate(
- Criteria criteria,
- final Criteria updateValues,
- Connection con)
- throws TorqueException
+ public static int doUpdate(
+ Criteria criteria,
+ ColumnValues updateValues,
+ Connection connection)
+ throws TorqueException
{
- Set<String> tables = SQLBuilder.getTableSet(criteria, null);
+ Query sql = createQuery(criteria);
+ sql.setType(Query.Type.UPDATE);
+ // ignore select columns in criteria
+ sql.getSelectClause().clear();
+ List<JdbcTypedValue> replacementObjects
+ = new ArrayList<JdbcTypedValue>();
+ for (Map.Entry<String, JdbcTypedValue> updateValue
+ : updateValues.entrySet())
+ {
+ String columnName = updateValue.getKey();
+ if (columnName.lastIndexOf(".") != -1)
+ {
+ columnName = columnName.substring(
+ columnName.lastIndexOf(".") + 1);
+ }
+ sql.getSelectClause().add(columnName);
+ replacementObjects.add(updateValue.getValue());
+ }
+
+ PreparedStatement preparedStatement = null;
try
{
- processTables(criteria, tables, con, new ProcessCallback() {
- public void process (String table, String dbName, Record rec)
- throws Exception
- {
- // Callback must be called with table name without Schema!
- BasePeer.insertOrUpdateRecord(rec, table, dbName, updateValues);
- }
- });
+ preparedStatement = connection.prepareStatement(sql.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++;
+ }
+ long startTime = System.currentTimeMillis();
+ log.debug("Executing update " + sql.toString()
+ + " using parameters " + replacementObjects);
+
+ int affectedRows = preparedStatement.executeUpdate();
+ long queryEndTime = System.currentTimeMillis();
+ log.trace("update took " + (queryEndTime - startTime)
+ + " milliseconds");
+
+ preparedStatement.close();
+ preparedStatement = null;
+ return affectedRows;
}
- catch (Exception e)
+ catch (SQLException e)
{
- throwTorqueException(e);
+ throw new TorqueException(e);
+ }
+ finally
+ {
+ if (preparedStatement != null)
+ {
+ try
+ {
+ preparedStatement.close();
+ }
+ catch (SQLException e)
+ {
+ log.warn("error closing prepared statement", e);
+ }
+ }
}
}
@@ -1367,23 +1767,6 @@ public abstract class BasePeer
}
/**
- * If the user specified that (s)he only wants to retrieve a
- * single record and multiple records are retrieved, this method
- * is called to handle the situation. The default behavior is to
- * throw an exception, but subclasses can override this method as
- * needed.
- *
- * @param ds The DataSet which contains multiple records.
- * @exception TooManyRowsException Couldn't handle multiple records.
- */
- protected static void handleMultipleRecords(DataSet ds)
- throws TooManyRowsException
- {
- throw new TooManyRowsException("Criteria expected single Record and "
- + "Multiple Records were selected");
- }
-
- /**
* This method returns the MapBuilder specified in the name
* parameter. You should pass in the full path to the class, ie:
* org.apache.torque.util.db.map.TurbineMapBuilder. The
@@ -1401,112 +1784,6 @@ public abstract class BasePeer
}
/**
- * Performs a SQL <code>select</code> using a PreparedStatement.
- * Note: this method does not handle null criteria values.
- *
- * @param criteria
- * @param con
- * @return a List of Record objects.
- * @throws TorqueException Error performing database query.
- */
- public static List<Record> doPSSelect(Criteria criteria, Connection con)
- throws TorqueException
- {
- List<Record> v = null;
-
- StringBuffer qry = new StringBuffer();
- List<Object> params = new ArrayList<Object>(criteria.size());
-
- createPreparedStatement(criteria, qry, params);
-
- PreparedStatement statement = null;
- try
- {
- statement = con.prepareStatement(qry.toString());
-
- for (int i = 0; i < params.size(); i++)
- {
- Object param = params.get(i);
- if (param instanceof java.sql.Date)
- {
- statement.setDate(i + 1, (java.sql.Date) param);
- }
- else if (param instanceof NumberKey)
- {
- statement.setBigDecimal(i + 1,
- ((NumberKey) param).getBigDecimal());
- }
- else if (param instanceof Integer)
- {
- statement.setInt(i + 1, ((Integer) param).intValue());
- }
- else
- {
- statement.setString(i + 1, param.toString());
- }
- }
-
- QueryDataSet qds = null;
- try
- {
- qds = new QueryDataSet(statement.executeQuery());
- v = getSelectResults(qds);
- }
- finally
- {
- VillageUtils.close(qds);
- }
- }
- catch (DataSetException e)
- {
- throwTorqueException(e);
- }
- catch (SQLException e)
- {
- throwTorqueException(e);
- }
- finally
- {
- if (statement != null)
- {
- try
- {
- statement.close();
- }
- catch (SQLException e)
- {
- throw new TorqueException(e);
- }
- }
- }
- return v;
- }
-
- /**
- * Do a Prepared Statement select according to the given criteria
- *
- * @param criteria
- * @return a List of Record objects.
- * @throws TorqueException Any exceptions caught during processing will be
- * rethrown wrapped into a TorqueException.
- */
- public static List<Record> doPSSelect(Criteria criteria) throws TorqueException
- {
- Connection con = Torque.getConnection(criteria.getDbName());
- List<Record> v = null;
-
- try
- {
- v = doPSSelect(criteria, con);
- }
- finally
- {
- Torque.closeConnection(con);
- }
- return v;
- }
-
- /**
* Create a new PreparedStatement. It builds a string representation
* of a query and a list of PreparedStatement parameters.
*
@@ -1655,116 +1932,46 @@ public abstract class BasePeer
}
/**
- * Process the result of a Table list generation.
- * This runs the statements onto the list of tables and
- * provides a callback hook to add functionality.
- *
- * This method should've been in SQLBuilder, but is uses the handleMultipleRecords callback thingie..
- *
- * @param crit The criteria
- * @param tables A set of Tables to run on
- * @param con The SQL Connection to run the statements on
- * @param pc A ProcessCallback object
+ * 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.
*
- * @throws Exception An Error occured (should be wrapped into TorqueException)
+ * @param columnValues The value to be checked for booleanint
+ * and booleanchar columns.
+ * @param defaultTableMap the table map to be used if the table name is
+ * not given in a column.
+ * @throws TorqueException if the database map for the criteria cannot be
+ * retrieved.
*/
- private static void processTables(Criteria crit, Set<String> tables, Connection con, ProcessCallback pc)
- throws Exception
+ public static void correctBooleans(
+ ColumnValues columnValues)
+ throws TorqueException
{
- String dbName = crit.getDbName();
- DB db = Torque.getDB(dbName);
- DatabaseMap dbMap = Torque.getDatabaseMap(dbName);
-
- // create the statements for the tables
- for (String table : tables)
+ TableMap table = columnValues.getTable();
+ for (Map.Entry<String, JdbcTypedValue> entry : columnValues.entrySet())
{
- KeyDef kd = new KeyDef();
- Set<String> whereClause = new HashSet<String>();
-
- ColumnMap[] columnMaps = dbMap.getTable(table).getColumns();
-
- for (int j = 0; j < columnMaps.length; j++)
+ String columnName = entry.getKey();
+ ColumnMap column = table.getColumn(columnName);
+ if (column != null)
{
- ColumnMap colMap = columnMaps[j];
- if (colMap.isPrimaryKey())
+ JdbcTypedValue columnValue = entry.getValue();
+ if ("BOOLEANINT".equals(column.getTorqueType()))
{
- kd.addAttrib(colMap.getColumnName());
+ columnValue.setValue(
+ Boolean.TRUE.equals(columnValue.getValue())
+ ? new Integer(1)
+ : new Integer(0));
}
-
- String key = new StringBuffer(colMap.getTableName())
- .append('.')
- .append(colMap.getColumnName())
- .toString();
-
- if (crit.containsKey(key))
+ else if ("BOOLEANCHAR".equals(column.getTorqueType()))
{
- if (crit
- .getComparison(key)
- .equals(Criteria.CUSTOM))
- {
- whereClause.add(crit.getString(key));
- }
- else
- {
- whereClause.add(
- SqlExpression.build(
- colMap.getColumnName(),
- crit.getValue(key),
- crit.getComparison(key),
- crit.isIgnoreCase(),
- db));
- }
- }
- }
-
- // Execute the statement for each table
- TableDataSet tds = null;
- try
- {
- String tableName = SQLBuilder.getFullTableName(table, dbName);
-
- // Get affected records.
- tds = new TableDataSet(con, tableName, kd);
- String sqlSnippet = StringUtils.join(whereClause.iterator(), " AND ");
-
- if (log.isDebugEnabled())
- {
- log.debug("BasePeer: whereClause=" + sqlSnippet);
- }
-
- tds.where(sqlSnippet);
- tds.fetchRecords();
-
- if (tds.size() > 1 && crit.isSingleRecord())
- {
- handleMultipleRecords(tds);
- }
-
- for (int j = 0; j < tds.size(); j++)
- {
- Record rec = tds.getRecord(j);
-
- if (pc != null)
- {
- // Table name _without_ schema!
- pc.process(table, dbName, rec);
- }
- }
- }
- finally
- {
- VillageUtils.close(tds);
+ columnValue.setValue(
+ Boolean.TRUE.equals(columnValue.getValue())
+ ? "Y"
+ : "N");
+ }
}
}
}
-
- /**
- * Inner Interface that defines the Callback method for
- * the Record Processing
- */
- protected interface ProcessCallback
- {
- void process (String table, String dbName, Record rec)
- throws Exception;
- }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: torque-dev-unsubscribe@db.apache.org
For additional commands, e-mail: torque-dev-help@db.apache.org