net.paoding.rose.jade.rowmapper.DefaultRowMapperFactory Maven / Gradle / Ivy
/*
* Copyright 2009-2010 the original author or authors.
*
* 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 i 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 net.paoding.rose.jade.rowmapper;
import net.paoding.rose.jade.annotation.RowHandler;
import net.paoding.rose.jade.annotation.StatementRowMapper;
import net.paoding.rose.jade.excetion.JadeException;
import net.paoding.rose.jade.statement.StatementMetaData;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
/**
* 支持DAO方法返回类型:
*
*
* - int、long等primitive:期望返回单列、1行
* - Integer、Long等包装类型的:期望返回单列、0行或1行
* - String、BigDecimal:期望返回单列,0行或1行
* - java.util.Date及其子类:期望返回单列,0行或1行
* - byte[]:期望返回单行、单列;列类型可转化为byte[]类型(比如blob类型)
* - Blob、Clob:期望返回单,0行或1行
* 数组(int[]、String[]等):期望返回单列,多行;
* - 数组(User[]等):期望返回多列,多行;
* - 集合(List<Integer>、Set<String>等): 期望返回单列,多行;
* - 集合(List<User>、Set<User>等): 期望返回单列,多行;
* - 映射(Map<String, Date>): 期望返回2列,多行
* - 映射(Map<String, User>): 期望返回多列,多行
* - 映射(Map<String, String[]>): 期望返回多列,多行
*
* @author 王志亮 [[email protected]]
* @author 廖涵 [[email protected]]
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class DefaultRowMapperFactory implements RowMapperFactory {
private static Log logger = LogFactory.getLog(RowMapperFactory.class);
private Map rowMappers = new HashMap();
@Override
public RowMapper getRowMapper(StatementMetaData modifier) {
RowHandler rowHandler = modifier.getAnnotation(RowHandler.class);
if (rowHandler != null) {
if (rowHandler.rowMapper() != RowHandler.ByDefault.class) {
try {
RowMapper rowMapper = rowHandler.rowMapper().newInstance();
if (logger.isInfoEnabled()) {
logger.info("using rowMapper " + rowMapper + " for " + modifier);
}
if (rowMapper instanceof StatementRowMapper) {
((StatementRowMapper) rowMapper).init(modifier);
}
return rowMapper;
} catch (Exception ex) {
throw new BeanInstantiationException(rowHandler.rowMapper(), ex.getMessage(),
ex);
}
}
}
//
Class> returnClassType = modifier.getMethod().getReturnType();
Class> rowType = getRowType(modifier);
// BUGFIX: SingleColumnRowMapper 处理 Primitive Type 抛异常
if (rowType.isPrimitive()) {
rowType = ClassUtils.primitiveToWrapper(rowType);
}
// 根据类型创建 RowMapper
RowMapper rowMapper;
// 返回单列的查询的(或者返回只有2列的Map类型查询的)
if (TypeUtils.isColumnType(rowType)) {
if (Map.class.isAssignableFrom(returnClassType)) {
rowMapper = new MapEntryColumnRowMapper(modifier, rowType);
} else {
rowMapper = new SingleColumnRowMapper(rowType);
}
}
// 返回多列的,用Bean对象、集合、映射、数组来表示每一行的
else {
if (rowType == Map.class) {
rowMapper = new ColumnMapRowMapper();
} else if (rowType.isArray()) {
rowMapper = new ArrayRowMapper(rowType);
} else if ((rowType == List.class) || (rowType == Collection.class)) {
rowMapper = new ListRowMapper(modifier);
} else if (rowType == Set.class) {
rowMapper = new SetRowMapper(modifier);
} else {
boolean checkColumns = (rowHandler == null) || rowHandler.checkColumns();
boolean checkProperties = (rowHandler != null) && rowHandler.checkProperties();
boolean toOptional = rowType == Optional.class;
boolean toStream = rowType == Stream.class;
Class>[] genericReturnTypes = modifier.getGenericReturnTypes();
StringBuilder key = new StringBuilder(rowType.getName());
key.append("[checkColumns=").append(checkColumns).append("&checkProperties=").append(checkProperties);
if (genericReturnTypes != null && genericReturnTypes.length == 1) {
key.append("&genericReturnTypes=").append(genericReturnTypes[0].getTypeName());
}
rowMapper = rowMappers.get(key.append("]").toString());
if (rowMapper == null) {
if (toOptional) {
if (genericReturnTypes == null || genericReturnTypes.length != 1) {
throw new JadeException("option generic paradigm [T] is null or length not equal to 1");
}
rowType = genericReturnTypes[0];
} else if (toStream) {
if (genericReturnTypes == null || genericReturnTypes.length != 1) {
throw new JadeException("stream generic paradigm [T] is null or length not equal to 1");
}
rowType = genericReturnTypes[0];
}
// jade's BeanPropertyRowMapper here
rowMapper =
new BeanPropertyRowMapper(rowType, checkColumns, checkProperties, toOptional);
rowMappers.put(key.toString(), rowMapper);
}
}
// 如果DAO方法最终返回的是Map,rowMapper要返回Map.Entry对象
if (Map.class.isAssignableFrom(returnClassType)) {
rowMapper = new MapEntryRowMapper(modifier, rowMapper);
}
}
if (logger.isInfoEnabled()) {
logger.info("using rowMapper " + rowMapper + " for " + modifier);
}
return rowMapper;
}
// 获得返回的集合元素类型
private static Class> getRowType(StatementMetaData statementMetaData) {
Class> returnClassType = statementMetaData.getReturnType();
if (Collection.class.isAssignableFrom(returnClassType)//
|| Iterable.class == returnClassType //
|| Iterator.class == returnClassType) {
return getRowTypeFromCollectionType(statementMetaData, returnClassType);
} //
else if (Map.class.isAssignableFrom(returnClassType)) {
return getRowTypeFromMapType(statementMetaData, returnClassType);
}
//
else if (returnClassType.isArray() && returnClassType != byte[].class) {
// 数组类型, 支持多重数组
return returnClassType.getComponentType();
}
// 此时代表整个DAO方法只关心结果集第一行
return returnClassType;
}
private static Class> getRowTypeFromMapType(StatementMetaData modifier,
Class> returnClassType) {
Class> rowType;
// 获取 Map 值元素类型
Class>[] genericTypes = modifier.getGenericReturnTypes();
if (genericTypes.length != 2) {
throw new IllegalArgumentException("the returned generic type '"
+ returnClassType.getName() + "' should has two actual type parameters.");
}
rowType = genericTypes[1]; // 取 V 类型
return rowType;
}
private static Class> getRowTypeFromCollectionType(StatementMetaData modifier,
Class> returnClassType) {
Class> rowType;
// 仅支持 List/ArrayList/LinkedList, CollectionIterable/Iterator, Set/HashSet
if ((returnClassType != List.class) && (returnClassType != ArrayList.class) && (returnClassType != LinkedList.class)//
&& (returnClassType != Collection.class) && (returnClassType != Iterable.class) && (returnClassType != Iterator.class)
&& (returnClassType != Set.class) && (returnClassType != HashSet.class)
) {
throw new IllegalArgumentException("error collection type " + returnClassType.getName()
+ "; only support List/ArrayList/LinkedList, CollectionIterable/Iterator, Set/HashSet");
}
// 获取集合元素类型
Class>[] genericTypes = modifier.getGenericReturnTypes();
if (genericTypes.length != 1) {
throw new IllegalArgumentException("the returned generic type '"
+ returnClassType.getName() + "' should has a actual type parameter.");
}
rowType = genericTypes[0];
return rowType;
}
}