All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jfaster.mango.mapper.BeanPropertyRowMapper Maven / Gradle / Ivy

/*
 * Copyright 2014 mango.jfaster.org
 *
 * The Mango Project 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.jfaster.mango.mapper;

import org.jfaster.mango.invoker.InvokerCache;
import org.jfaster.mango.invoker.SetterInvoker;
import org.jfaster.mango.invoker.UnreachablePropertyException;
import org.jfaster.mango.type.TypeHandler;
import org.jfaster.mango.type.TypeHandlerRegistry;
import org.jfaster.mango.util.PropertyTokenizer;
import org.jfaster.mango.util.Strings;
import org.jfaster.mango.util.jdbc.ResultSetWrapper;
import org.jfaster.mango.util.logging.InternalLogger;
import org.jfaster.mango.util.logging.InternalLoggerFactory;
import org.jfaster.mango.util.reflect.Reflection;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 单列或多列组装对象RowMapper
 *
 * @author ash
 */
public class BeanPropertyRowMapper implements RowMapper {

  private final static InternalLogger logger = InternalLoggerFactory.getInstance(BeanPropertyRowMapper.class);

  private Class mappedClass;

  private Map invokerMap;

  private Map columnToPropertyMap;

  private boolean checkColumn;

  public BeanPropertyRowMapper(Class mappedClass, Map propertyToColumnMap, boolean checkColumn) {
    initialize(mappedClass, propertyToColumnMap, checkColumn);
  }

  protected void initialize(Class mappedClass, Map propertyToColumnMap, boolean checkColumn) {
    this.mappedClass = mappedClass;
    this.checkColumn = checkColumn;
    this.columnToPropertyMap = new HashMap();
    this.invokerMap = new HashMap();

    // 初始化columnToPropertyPathMap
    for (Map.Entry entry : propertyToColumnMap.entrySet()) {
      String property = entry.getKey();
      PropertyTokenizer propToken = new PropertyTokenizer(property);
      if (propToken.hasNext()) {
        columnToPropertyMap.put(entry.getValue().toLowerCase(), property);
      }
    }

    // 初始化invokerMap
    List invokers = InvokerCache.getSetterInvokers(mappedClass);
    for (SetterInvoker invoker : invokers) {
      String column = propertyToColumnMap.get(invoker.getName());
      if (column != null) { // 使用配置映射
        invokerMap.put(column.toLowerCase(), invoker);
      } else { // 使用约定映射
        invokerMap.put(invoker.getName().toLowerCase(), invoker);
        String underscoredName = Strings.underscoreName(invoker.getName());
        if (!invoker.getName().toLowerCase().equals(underscoredName)) {
          invokerMap.put(underscoredName, invoker);
        }
      }
    }
  }

  public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
    T mappedObject = Reflection.instantiate(mappedClass);

    ResultSetWrapper rsw = new ResultSetWrapper(rs);
    int columnCount = rsw.getColumnCount();

    for (int index = 1; index <= columnCount; index++) {
      String columnName = rsw.getColumnName(index);
      String lowerCaseColumnName = columnName.toLowerCase();
      String propertyPath = columnToPropertyMap.get(lowerCaseColumnName);
      if (propertyPath != null) { // 使用自定义多级映射
        setValueByPropertyPath(mappedObject, propertyPath, rsw, index, rowNumber);
      } else {
        PropertyTokenizer prop = new PropertyTokenizer(columnName);
        if (prop.hasNext()) { // select语句中的字段存在多级映射
          setValueByPropertyPath(mappedObject, columnName, rsw, index, rowNumber);
        } else { // 单级映射(包含约定和自定义)
          setValueByProperty(mappedObject, lowerCaseColumnName, rsw, index, rowNumber);
        }
      }
    }
    return mappedObject;
  }

  private void setValueByPropertyPath(Object mappedObject, String propertyPath, ResultSetWrapper rsw,
                                      int index, int rowNumber) throws SQLException {

    FunctionalSetterInvokerGroup g = null;
    try {
      g = FunctionalSetterInvokerGroup.create(mappedClass, propertyPath);
    } catch (UnreachablePropertyException e) {
      if (checkColumn) {
        throw new MappingException("Unable to map column '" + rsw.getColumnName(index) +
            "' to property '" + propertyPath + "'");
      }
    }
    if (g != null) {
      TypeHandler typeHandler = TypeHandlerRegistry.getTypeHandler(g.getTargetType(), rsw.getJdbcType(index));
      Object value = typeHandler.getResult(rsw.getResultSet(), index);
      if (logger.isDebugEnabled() && rowNumber == 0) {
        logger.debug("Mapping column '" + rsw.getColumnName(index) + "' to property '" +
            propertyPath + "' of type " + g.getTargetType());
      }
      g.invoke(mappedObject, value);
    }
  }

  private void setValueByProperty(Object mappedObject, String lowerCaseColumnName, ResultSetWrapper rsw,
                                  int index, int rowNumber) throws SQLException {

    SetterInvoker invoker = invokerMap.get(lowerCaseColumnName);
    if (invoker != null) {
      TypeHandler typeHandler = TypeHandlerRegistry.getTypeHandler(invoker.getParameterRawType(), rsw.getJdbcType(index));
      Object value = typeHandler.getResult(rsw.getResultSet(), index);
      if (logger.isDebugEnabled() && rowNumber == 0) {
        logger.debug("Mapping column '" + rsw.getColumnName(index) + "' to property '" +
            invoker.getName() + "' of type " + invoker.getParameterRawType());
      }
      invoker.invoke(mappedObject, value);
    } else {
      if (checkColumn) {
        throw new MappingException("Unable to map column '" + rsw.getColumnName(index) +
            "' to any property of '" + mappedClass + "'");
      }
    }
  }

  @Override
  public Class getMappedClass() {
    return mappedClass;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy