/*
 * Licensed 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.jdbi.v3.core.mapper;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.UnaryOperator;

import org.jdbi.v3.core.statement.StatementContext;

Yo dawg, I heard you like maps, so I made you a mapper that maps rows into Map<String,Object>. Map keys are column names, while map values are the values in those columns. Map keys are converted to lowercase by default.
See Also:
/** * Yo dawg, I heard you like maps, so I made you a mapper that maps rows into {@code Map<String,Object>}. Map * keys are column names, while map values are the values in those columns. Map keys are converted to lowercase by * default. * * @see GenericMapMapperFactory */
public class MapMapper implements RowMapper<Map<String, Object>> {
Deprecated:remove
/** * @deprecated remove */
@Deprecated private final Function<StatementContext, UnaryOperator<String>> caseStrategy;
Constructs a new MapMapper and delegates case control to MapMappers.
/** * Constructs a new MapMapper and delegates case control to MapMappers. */
public MapMapper() { caseStrategy = ctx -> ctx.getConfig(MapMappers.class).getCaseChange(); }
Constructs a new MapMapper
Params:
  • toLowerCase – if true, column names are converted to lowercase in the mapped Map. If false, nothing is done. Use the other constructor to delegate case control to MapMappers instead.
/** * Constructs a new MapMapper * @param toLowerCase if true, column names are converted to lowercase in the mapped {@link Map}. If false, nothing is done. Use the other constructor to delegate case control to MapMappers instead. */
// TODO deprecate when MapMappers.caseChange is out of beta public MapMapper(boolean toLowerCase) { caseStrategy = toLowerCase ? ctx -> CaseStrategy.LOCALE_LOWER : ctx -> CaseStrategy.NOP; } @Override public Map<String, Object> map(ResultSet rs, StatementContext ctx) throws SQLException { return specialize(rs, ctx).map(rs, ctx); } @Override public RowMapper<Map<String, Object>> specialize(ResultSet rs, StatementContext ctx) throws SQLException { final List<String> columnNames = getColumnNames(rs, caseStrategy.apply(ctx)); return (r, c) -> { Map<String, Object> row = new LinkedHashMap<>(columnNames.size()); for (int i = 0; i < columnNames.size(); i++) { row.put(columnNames.get(i), rs.getObject(i + 1)); } return row; }; } private static List<String> getColumnNames(ResultSet rs, UnaryOperator<String> caseChange) throws SQLException { // important: ordered and unique Set<String> columnNames = new LinkedHashSet<>(); ResultSetMetaData meta = rs.getMetaData(); int columnCount = meta.getColumnCount(); for (int i = 0; i < columnCount; i++) { String columnName = meta.getColumnName(i + 1); String alias = meta.getColumnLabel(i + 1); String name = caseChange.apply(alias == null ? columnName : alias); boolean added = columnNames.add(name); if (!added) { throw new RuntimeException("column " + name + " appeared twice in this resultset!"); } } return new ArrayList<>(columnNames); } }