KeyedHandler.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.dbutils.handlers;

  18. import java.sql.ResultSet;
  19. import java.sql.SQLException;
  20. import java.util.Map;

  21. import org.apache.commons.dbutils.RowProcessor;

  22. /**
  23.  * <p>
  24.  * {@code ResultSetHandler} implementation that returns a Map of Maps.
  25.  * {@code ResultSet} rows are converted into Maps which are then stored
  26.  * in a Map under the given key.
  27.  * </p>
  28.  * <p>
  29.  * If you had a Person table with a primary key column called ID, you could
  30.  * retrieve rows from the table like this:
  31.  * <pre>
  32.  * ResultSetHandler h = new KeyedHandler("id");
  33.  * Map found = (Map) queryRunner.query("select id, name, age from person", h);
  34.  * Map jane = (Map) found.get(new Long(1)); // jane's id is 1
  35.  * String janesName = (String) jane.get("name");
  36.  * Integer janesAge = (Integer) jane.get("age");
  37.  * </pre>
  38.  * Note that the "id" passed to KeyedHandler and "name" and "age" passed to the
  39.  * returned Map's get() method can be in any case.  The data types returned for
  40.  * name and age are dependent upon how your JDBC driver converts SQL column
  41.  * types from the Person table into Java types.
  42.  * &lt;/p&gt;
  43.  * <p>This class is thread safe.</p>
  44.  *
  45.  * @param <K> The type of the key
  46.  * @see org.apache.commons.dbutils.ResultSetHandler
  47.  * @since 1.1
  48.  */
  49. public class KeyedHandler<K> extends AbstractKeyedHandler<K, Map<String, Object>> {

  50.     /**
  51.      * The RowProcessor implementation to use when converting rows
  52.      * into Objects.
  53.      */
  54.     protected final RowProcessor convert;

  55.     /**
  56.      * The column index to retrieve key values from.  Defaults to 1.
  57.      */
  58.     protected final int columnIndex;

  59.     /**
  60.      * The column name to retrieve key values from.  Either columnName or
  61.      * columnIndex will be used but never both.
  62.      */
  63.     protected final String columnName;

  64.     /**
  65.      * Creates a new instance of KeyedHandler.  The value of the first column
  66.      * of each row will be a key in the Map.
  67.      */
  68.     public KeyedHandler() {
  69.         this(ArrayHandler.ROW_PROCESSOR, 1, null);
  70.     }

  71.     /**
  72.      * Creates a new instance of KeyedHandler.
  73.      *
  74.      * @param columnIndex The values to use as keys in the Map are
  75.      * retrieved from the column at this index.
  76.      */
  77.     public KeyedHandler(final int columnIndex) {
  78.         this(ArrayHandler.ROW_PROCESSOR, columnIndex, null);
  79.     }

  80.     /**
  81.      * Creates a new instance of KeyedHandler.  The value of the first column
  82.      * of each row will be a key in the Map.
  83.      *
  84.      * @param convert The {@code RowProcessor} implementation
  85.      * to use when converting rows into Maps
  86.      */
  87.     public KeyedHandler(final RowProcessor convert) {
  88.         this(convert, 1, null);
  89.     }

  90.     /** Private Helper
  91.      * @param convert The {@code RowProcessor} implementation
  92.      * to use when converting rows into Maps
  93.      * @param columnIndex The values to use as keys in the Map are
  94.      * retrieved from the column at this index.
  95.      * @param columnName The values to use as keys in the Map are
  96.      * retrieved from the column with this name.
  97.      */
  98.     private KeyedHandler(final RowProcessor convert, final int columnIndex,
  99.             final String columnName) {
  100.         this.convert = convert;
  101.         this.columnIndex = columnIndex;
  102.         this.columnName = columnName;
  103.     }

  104.     /**
  105.      * Creates a new instance of KeyedHandler.
  106.      *
  107.      * @param columnName The values to use as keys in the Map are
  108.      * retrieved from the column with this name.
  109.      */
  110.     public KeyedHandler(final String columnName) {
  111.         this(ArrayHandler.ROW_PROCESSOR, 1, columnName);
  112.     }
  113.     /**
  114.      * This factory method is called by {@code handle()} to retrieve the
  115.      * key value from the current {@code ResultSet} row.  This
  116.      * implementation returns {@code ResultSet.getObject()} for the
  117.      * configured key column name or index.
  118.      * @param rs ResultSet to create a key from
  119.      * @return Object from the configured key column name/index
  120.      *
  121.      * @throws SQLException if a database access error occurs
  122.      * @throws ClassCastException if the class datatype does not match the column type
  123.      */
  124.     // We assume that the user has picked the correct type to match the column
  125.     // so getObject will return the appropriate type and the cast will succeed.
  126.     @SuppressWarnings("unchecked")
  127.     @Override
  128.     protected K createKey(final ResultSet rs) throws SQLException {
  129.         return columnName == null ?
  130.                (K) rs.getObject(columnIndex) :
  131.                (K) rs.getObject(columnName);
  132.     }

  133.     /**
  134.      * This factory method is called by {@code handle()} to store the
  135.      * current {@code ResultSet} row in some object. This
  136.      * implementation returns a {@code Map} with case insensitive column
  137.      * names as keys.  Calls to {@code map.get("COL")} and
  138.      * {@code map.get("col")} return the same value.
  139.      * @param resultSet ResultSet to create a row from
  140.      * @return Object typed Map containing column names to values
  141.      * @throws SQLException if a database access error occurs
  142.      */
  143.     @Override
  144.     protected Map<String, Object> createRow(final ResultSet resultSet) throws SQLException {
  145.         return this.convert.toMap(resultSet);
  146.     }

  147. }