001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.dbutils.handlers; 018 019 import java.sql.ResultSet; 020 import java.sql.SQLException; 021 import java.util.Map; 022 023 import org.apache.commons.dbutils.RowProcessor; 024 025 /** 026 * <p> 027 * <code>ResultSetHandler</code> implementation that returns a Map of Maps. 028 * <code>ResultSet</code> rows are converted into Maps which are then stored 029 * in a Map under the given key. 030 * </p> 031 * <p> 032 * If you had a Person table with a primary key column called ID, you could 033 * retrieve rows from the table like this: 034 * <pre> 035 * ResultSetHandler h = new KeyedHandler("id"); 036 * Map found = (Map) queryRunner.query("select id, name, age from person", h); 037 * Map jane = (Map) found.get(new Long(1)); // jane's id is 1 038 * String janesName = (String) jane.get("name"); 039 * Integer janesAge = (Integer) jane.get("age"); 040 * </pre> 041 * Note that the "id" passed to KeyedHandler and "name" and "age" passed to the 042 * returned Map's get() method can be in any case. The data types returned for 043 * name and age are dependent upon how your JDBC driver converts SQL column 044 * types from the Person table into Java types. 045 * </p> 046 * <p>This class is thread safe.</p> 047 * 048 * @see org.apache.commons.dbutils.ResultSetHandler 049 * @since DbUtils 1.1 050 */ 051 public class KeyedHandler extends AbstractKeyedHandler<Object, Map<String, Object>> { 052 053 /** 054 * The RowProcessor implementation to use when converting rows 055 * into Objects. 056 */ 057 protected final RowProcessor convert; 058 059 /** 060 * The column index to retrieve key values from. Defaults to 1. 061 */ 062 protected final int columnIndex; 063 064 /** 065 * The column name to retrieve key values from. Either columnName or 066 * columnIndex will be used but never both. 067 */ 068 protected final String columnName; 069 070 /** 071 * Creates a new instance of KeyedHandler. The value of the first column 072 * of each row will be a key in the Map. 073 */ 074 public KeyedHandler() { 075 this(ArrayHandler.ROW_PROCESSOR, 1, null); 076 } 077 078 /** 079 * Creates a new instance of KeyedHandler. The value of the first column 080 * of each row will be a key in the Map. 081 * 082 * @param convert The <code>RowProcessor</code> implementation 083 * to use when converting rows into Maps 084 */ 085 public KeyedHandler(RowProcessor convert) { 086 this(convert, 1, null); 087 } 088 089 /** 090 * Creates a new instance of KeyedHandler. 091 * 092 * @param columnIndex The values to use as keys in the Map are 093 * retrieved from the column at this index. 094 */ 095 public KeyedHandler(int columnIndex) { 096 this(ArrayHandler.ROW_PROCESSOR, columnIndex, null); 097 } 098 099 /** 100 * Creates a new instance of KeyedHandler. 101 * 102 * @param columnName The values to use as keys in the Map are 103 * retrieved from the column with this name. 104 */ 105 public KeyedHandler(String columnName) { 106 this(ArrayHandler.ROW_PROCESSOR, 1, columnName); 107 } 108 109 /** Private Helper 110 * @param convert The <code>RowProcessor</code> implementation 111 * to use when converting rows into Maps 112 * @param columnIndex The values to use as keys in the Map are 113 * retrieved from the column at this index. 114 * @param columnName The values to use as keys in the Map are 115 * retrieved from the column with this name. 116 */ 117 private KeyedHandler(RowProcessor convert, int columnIndex, 118 String columnName) { 119 super(); 120 this.convert = convert; 121 this.columnIndex = columnIndex; 122 this.columnName = columnName; 123 } 124 /** 125 * This factory method is called by <code>handle()</code> to retrieve the 126 * key value from the current <code>ResultSet</code> row. This 127 * implementation returns <code>ResultSet.getObject()</code> for the 128 * configured key column name or index. 129 * @param rs ResultSet to create a key from 130 * @return Object from the configured key column name/index 131 * @throws SQLException if a database access error occurs 132 */ 133 @Override 134 protected Object createKey(ResultSet rs) throws SQLException { 135 return (columnName == null) ? rs.getObject(columnIndex) : rs 136 .getObject(columnName); 137 } 138 139 /** 140 * This factory method is called by <code>handle()</code> to store the 141 * current <code>ResultSet</code> row in some object. This 142 * implementation returns a <code>Map</code> with case insensitive column 143 * names as keys. Calls to <code>map.get("COL")</code> and 144 * <code>map.get("col")</code> return the same value. 145 * @param rs ResultSet to create a row from 146 * @return Object typed Map containing column names to values 147 * @throws SQLException if a database access error occurs 148 */ 149 @Override 150 protected Map<String, Object> createRow(ResultSet rs) throws SQLException { 151 return this.convert.toMap(rs); 152 } 153 154 }