通用jdbc结果集映射工具RowMapper

这篇文章介绍了一个jdbc中通用的结果集映射工具。

代码

/**
 * 
 */
package com.cmc.tools.jdbc;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Map;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.util.CollectionUtils;

import com.cmc.model.common.BaseModel;

/**
 * @desc 通用值映射类
 * @author cmc
 * @email chenmingchuan@all-in-data.com
 * @date 2019年12月30日 上午9:34:14
 */
public class AdbCommonRowMapper<T extends BaseModel> implements RowMapper<T>{
	
	private Class<T> targetClazz;
	
	private Map<String,String> replaceMap ;
	
	public AdbCommonRowMapper(Class<T> targetClazz) {
		this.targetClazz = targetClazz;
	}
	
	public AdbCommonRowMapper(Class<T> targetClazz, Map<String, String> replaceMap) {
		this.targetClazz = targetClazz;
		this.replaceMap = replaceMap;
	}

	@Override
	public T mapRow(ResultSet rs, int rowNum) throws SQLException {
		
		//初始化
		T t = newInstance() ;
		if(null == t) {
			throw new RuntimeException("初始化model失败!");
		}
		//映射字段
		try {
			mapParams(t, rs) ;
		} catch (Exception e) {
			throw new RuntimeException("映射字段时出现异常!" + e) ;
		}
		return t ;
	}

	/**
	 * <p>功能: 映射字段</p>
	 * @param t
	 * @param rs
	 * @throws Exception 
	 */
	private void mapParams(T t, ResultSet rs) throws Exception {
		Field[] fields = t.getClass().getDeclaredFields();
		for(Field field : fields) {
			//读取数据库里的值
			Object value = getDBValue(rs, field.getType(), field.getName()) ;
			//调用set方法设置值
			PropertyDescriptor pd = new PropertyDescriptor(field.getName(), t.getClass()) ;
			Method rM = pd.getWriteMethod() ;
			rM.invoke(t, value) ;
		}			
	}


	/**
	 * <p>功能: 读取数据库里的变量值</p>
	 * @param rs
	 * @param type
	 * @param name
	 * @return
	 * @throws SQLException 
	 */
	private Object getDBValue(ResultSet rs, Class<?> type, String name) throws SQLException {
		String colName = toColName(name) ;
		//如果结果集没有这个字段,返回空
		if(!isContainCol(rs, colName)) {
			return null ;
		}
		
		if(type == Integer.class) {
			return rs.getInt(colName) ;
		}
		else if(type == int.class) {
			return rs.getInt(colName) ;
		}
		else if(type == Long.class) {
			return rs.getLong(colName) ;
		}
		else if(type == long.class) {
			return rs.getLong(colName) ;
		}
		else if(type == Double.class) {
			return rs.getDouble(colName) ;
		}
		else if(type == double.class) {
			return rs.getDouble(colName) ;
		}
		else if(type == Boolean.class) {
			return rs.getBoolean(colName) ;
		}
		else if(type == boolean.class) {
			return rs.getBoolean(colName) ;
		}
		else if(type == Short.class) {
			return rs.getShort(colName) ;
		}
		else if(type == short.class) {
			return rs.getShort(colName) ;
		}
		else if(type == String.class) {
			return rs.getString(colName) == null ? null : rs.getString(colName) ;
		}
		else if(type == LocalDateTime.class) {
			return rs.getTimestamp(colName) == null ? null :rs.getTimestamp(colName).toLocalDateTime() ;
		}
		else if(type == LocalDate.class) {
			return rs.getTimestamp(colName) == null ? null :rs.getTimestamp(colName).toLocalDateTime().toLocalDate() ;
		}
		else if(type.isEnum()) {
			String enumValue = rs.getString(colName) == null ? null : rs.getString(colName) ;
			Object enumType = getEnum(type, enumValue) ;
			return enumType ;
		}
		else {
			throw new RuntimeException("暂时不支持数据类型" + type) ;
		}
	}


	/**
	 * <p>功能: 通过名字获取具体的枚举实例</p>
	 * @param type
	 * @param enumValue
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private Object getEnum(Class<?> type, String enumValue) {
		if(enumValue == null) {
			return null ;
		}
		try {
			Class<Enum<?>> clazz = (Class<Enum<?>>) Class.forName(type.getName());
	        Enum<?>[] objects = clazz.getEnumConstants();
	        for (Enum<?> object : objects) {
	        	if(object.name().equals(enumValue)) {
	        		return object ;
	        	}
	        }
	        throw new RuntimeException(type + "无此枚举值" + enumValue) ;
		} catch (Exception e) {
			throw new RuntimeException("实例化枚举实例失败!" + e) ;
		}
	}

	/**
	 * <p>功能: 判断数据库查询结果集有无相关字段</p>
	 * @param colName
	 * @return
	 */
	private boolean isContainCol(ResultSet rs, String colName) {
		try {
			rs.findColumn(colName) ;
			return true ;
		}catch (Exception e) {
			return false ;
		}
	}

	/**
	 * <p>功能: 按驼峰命名规则将model里的字段名转换为数据库里的字段名</p>
	 * @param name
	 * @return
	 */
	private String toColName(String name) {
		//如果字段有替换,替换上
		if(!CollectionUtils.isEmpty(replaceMap) && replaceMap.containsKey(name)) {
			name = replaceMap.get(name) ;
		}
		//按驼峰规则处理model字段名
		for(char c : name.toCharArray()) {
			if(Character.isUpperCase(c)) {
				name = name.replace(c + "", "_" + Character.toLowerCase(c)) ;
			}
		}
		return name;
	}

	/**
	 * <p>功能: 初始化对象</p>
	 * @param clazz
	 * @return
	 */
	private T newInstance() {
		T t = null ;
		try {
			t = (T) targetClazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
       }
		return t ;
	}

}
 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值