这篇文章介绍了一个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 ;
}
}