/* | |
* 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. | |
*/ | |
package org.apache.commons.dbutils.handlers; | |
import java.sql.ResultSet; | |
import java.sql.SQLException; | |
import java.util.Map; | |
import org.apache.commons.dbutils.RowProcessor; | |
/** | |
* <p> | |
* {@code ResultSetHandler} implementation that returns a Map of Maps. | |
* {@code ResultSet} rows are converted into Maps which are then stored | |
* in a Map under the given key. | |
* </p> | |
* <p> | |
* If you had a Person table with a primary key column called ID, you could | |
* retrieve rows from the table like this: | |
* <pre> | |
* ResultSetHandler h = new KeyedHandler("id"); | |
* Map found = (Map) queryRunner.query("select id, name, age from person", h); | |
* Map jane = (Map) found.get(new Long(1)); // jane's id is 1 | |
* String janesName = (String) jane.get("name"); | |
* Integer janesAge = (Integer) jane.get("age"); | |
* </pre> | |
* Note that the "id" passed to KeyedHandler and "name" and "age" passed to the | |
* returned Map's get() method can be in any case. The data types returned for | |
* name and age are dependent upon how your JDBC driver converts SQL column | |
* types from the Person table into Java types. | |
* </p> | |
* <p>This class is thread safe.</p> | |
* | |
* @param <K> The type of the key | |
* @see org.apache.commons.dbutils.ResultSetHandler | |
* @since 1.1 | |
*/ | |
public class KeyedHandler<K> extends AbstractKeyedHandler<K, Map<String, Object>> { | |
/** | |
* The RowProcessor implementation to use when converting rows | |
* into Objects. | |
*/ | |
protected final RowProcessor convert; | |
/** | |
* The column index to retrieve key values from. Defaults to 1. | |
*/ | |
protected final int columnIndex; | |
/** | |
* The column name to retrieve key values from. Either columnName or | |
* columnIndex will be used but never both. | |
*/ | |
protected final String columnName; | |
/** | |
* Creates a new instance of KeyedHandler. The value of the first column | |
* of each row will be a key in the Map. | |
*/ | |
public KeyedHandler() { | |
this(ArrayHandler.ROW_PROCESSOR, 1, null); | |
} | |
/** | |
* Creates a new instance of KeyedHandler. | |
* | |
* @param columnIndex The values to use as keys in the Map are | |
* retrieved from the column at this index. | |
*/ | |
public KeyedHandler(final int columnIndex) { | |
this(ArrayHandler.ROW_PROCESSOR, columnIndex, null); | |
} | |
/** | |
* Creates a new instance of KeyedHandler. The value of the first column | |
* of each row will be a key in the Map. | |
* | |
* @param convert The {@code RowProcessor} implementation | |
* to use when converting rows into Maps | |
*/ | |
public KeyedHandler(final RowProcessor convert) { | |
this(convert, 1, null); | |
} | |
/** Private Helper | |
* @param convert The {@code RowProcessor} implementation | |
* to use when converting rows into Maps | |
* @param columnIndex The values to use as keys in the Map are | |
* retrieved from the column at this index. | |
* @param columnName The values to use as keys in the Map are | |
* retrieved from the column with this name. | |
*/ | |
private KeyedHandler(final RowProcessor convert, final int columnIndex, | |
final String columnName) { | |
this.convert = convert; | |
this.columnIndex = columnIndex; | |
this.columnName = columnName; | |
} | |
/** | |
* Creates a new instance of KeyedHandler. | |
* | |
* @param columnName The values to use as keys in the Map are | |
* retrieved from the column with this name. | |
*/ | |
public KeyedHandler(final String columnName) { | |
this(ArrayHandler.ROW_PROCESSOR, 1, columnName); | |
} | |
/** | |
* This factory method is called by {@code handle()} to retrieve the | |
* key value from the current {@code ResultSet} row. This | |
* implementation returns {@code ResultSet.getObject()} for the | |
* configured key column name or index. | |
* @param rs ResultSet to create a key from | |
* @return Object from the configured key column name/index | |
* | |
* @throws SQLException if a database access error occurs | |
* @throws ClassCastException if the class datatype does not match the column type | |
*/ | |
// We assume that the user has picked the correct type to match the column | |
// so getObject will return the appropriate type and the cast will succeed. | |
@SuppressWarnings("unchecked") | |
@Override | |
protected K createKey(final ResultSet rs) throws SQLException { | |
return columnName == null ? | |
(K) rs.getObject(columnIndex) : | |
(K) rs.getObject(columnName); | |
} | |
/** | |
* This factory method is called by {@code handle()} to store the | |
* current {@code ResultSet} row in some object. This | |
* implementation returns a {@code Map} with case insensitive column | |
* names as keys. Calls to {@code map.get("COL")} and | |
* {@code map.get("col")} return the same value. | |
* @param rs ResultSet to create a row from | |
* @return Object typed Map containing column names to values | |
* @throws SQLException if a database access error occurs | |
*/ | |
@Override | |
protected Map<String, Object> createRow(final ResultSet rs) throws SQLException { | |
return this.convert.toMap(rs); | |
} | |
} |