Java tutorial
/* * 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 com.gzj.tulip.jade.rowmapper; 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.Set; import com.gzj.tulip.jade.annotation.RowHandler; 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 com.gzj.tulip.jade.annotation.StatementAware; import com.gzj.tulip.jade.statement.StatementMetaData; /** * ?DAO * <p> * <ul> * <li>int?longprimitive??1</li> * <li>Integer?Long??01</li> * <li>String?BigDecimal?01</li> * <li>java.util.Date???01</li> * <li>byte[]????byte[](blob)</li> * <li>Blob?Clob?01</li> * <li><code>(int[]?String[])?</li> * <li>(User[])</li> * <li>?(List<Integer>?Set<String>): ?</li> * <li>?(List<User>?Set<User>): ?</li> * <li>(Map<String, Date>): 2</li> * <li>(Map<String, User>): </li> * <li>(Map<String, String[]>): </li> * <ul> * * @author [qieqie.wang@gmail.com] * @author [in355hz@gmail.com] */ @SuppressWarnings({ "rawtypes", "unchecked" }) public class DefaultRowMapperFactory implements RowMapperFactory { private static Log logger = LogFactory.getLog(RowMapperFactory.class); private Map<String, RowMapper> rowMappers = new HashMap<String, RowMapper>(); @Override public RowMapper getRowMapper(StatementMetaData smd) { RowHandler rowHandler = smd.getAnnotation(RowHandler.class); // ? RowMapper RowMapper rowMapper = null; if (rowHandler != null) { if (rowHandler.rowMapper() != RowHandler.NotSettingRowMapper.class) { try { rowMapper = rowHandler.rowMapper().newInstance(); } catch (Exception ex) { throw new BeanInstantiationException(rowHandler.rowMapper(), ex.getMessage(), ex); } } else if (rowHandler.rowMapperFactory() != RowHandler.NotSettingRowMapperFactory.class) { try { RowMapperFactory rowMapperFactory = rowHandler.rowMapperFactory().newInstance(); rowMapper = rowMapperFactory.getRowMapper(smd); } catch (Exception ex) { throw new BeanInstantiationException(rowHandler.rowMapper(), ex.getMessage(), ex); } } } // if (rowMapper == null) { // Class<?> returnClassType = smd.getMethod().getReturnType(); Class<?> rowType = getRowType(smd); // BUGFIX: SingleColumnRowMapper ? Primitive Type if (rowType.isPrimitive()) { rowType = ClassUtils.primitiveToWrapper(rowType); } // ?(?2Map) if (TypeUtils.isColumnType(rowType)) { if (Map.class.isAssignableFrom(returnClassType)) { rowMapper = new MapEntryColumnRowMapper(smd, 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(smd); } else if (rowType == Set.class) { rowMapper = new SetRowMapper(smd); } else { boolean checkColumns = (rowHandler == null) ? true : rowHandler.checkColumns(); boolean checkProperties = (rowHandler == null) ? false : rowHandler.checkProperties(); String key = rowType.getName() + "[checkColumns=" + checkColumns + "&checkProperties=" + checkProperties + "]"; rowMapper = rowMappers.get(key); if (rowMapper == null) { rowMapper = new BeanPropertyRowMapper(rowType, checkColumns, checkProperties); // jade's BeanPropertyRowMapper here rowMappers.put(key, rowMapper); } } // DAOMaprowMapper?Map.Entry if (Map.class.isAssignableFrom(returnClassType)) { rowMapper = new MapEntryRowMapper(smd, rowMapper); } } } // if (rowMapper instanceof StatementAware) { ((StatementAware) rowMapper).setStatementMetaData(smd); } if (logger.isInfoEnabled()) { logger.info("using rowMapper " + rowMapper + " for " + smd); } 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<K, V> 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; } }