package cn.subanfaner.jdbc;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* <pre>
* <h3>实现原理: </h3>
* 1、使用ResultSet创建该类实例时,自动解析ResultSet中的数据,并将数据存储到 List<Map<String, Object>>中。
* 2、所有的检索方式都是基于存储有Map的List集合实现的。
* 3、基于List方式的检索适用于数据量少的ResultSet处理。(据量较大,建议使用ResultSet,在后续版本会补充基于ResultSet的检索方式)。
* <h3>注意: </h3>
* 1、只允许通过getInstance()方法获取此类的实例 (每次调用都会返回一个新的实例)。
* 2、在使用到数据库列名检索的方法中大小写是不敏感的,下划线也不是必须的。
* 3、该类包含也包含了首字母变大写、驼峰下划线互转的方法(后期如果用不到可能会移除此类)
* <h3>需要完善: </h3>
* 1、数据库元数据的使用,比如增加数据库类型与java类型之间的相互转换(这个要根据实际的业务需求来看)。
* 2、增加基于ResultSet的检索方式。
* 3、方法结构优化。
* ......
* </pre>
*
* @author dyw
* @date 2019年5月27日
*/
public class ResultSetEnhancer {
/** 元数据 */
private ResultSetMetaData resultMetaData;
/** 结果列表集合(每个Map存储一行数据信息) */
private List<Map<String, Object>> resultList;
/** 元数据列名-->元数据列类型映射集合 */
private Map<String, String> columnLabelTypeMap;
/** 总数据量 */
private int rowCount;
private ResultSetEnhancer(ResultSet resultSet) {
initColumnLabelTypeMap(resultSet);
initResultList(resultSet);
}
/**
* 注入元数据结果集,初始化元数据映射集合
*/
private void initColumnLabelTypeMap(ResultSet resultSet) {
try {
this.resultMetaData = resultSet.getMetaData();
columnLabelTypeMap = new HashMap<String, String>();
for (int i = 1; i <= resultMetaData.getColumnCount(); i++) {
columnLabelTypeMap.put(resultMetaData.getColumnLabel(i), resultMetaData.getColumnTypeName(i));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 初始化结果列表集合
*
* @param resultSet
*/
private void initResultList(ResultSet resultSet) {
try {
resultList = new ArrayList<Map<String, Object>>();
Set<String> columnLabelSet = columnLabelTypeMap.keySet();
while (resultSet.next()) {
Map<String, Object> temp = new HashMap<String, Object>();// 封装一行数据
for (String columnLabel : columnLabelSet) {
// 数据库列名全部去掉"_"转换成小写
temp.put(deletUnderLineAndToLowerCase(columnLabel), resultSet.getObject(columnLabel));
}
resultList.add(temp);
}
rowCount = resultList.size();// 记录数据总量
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 提供获取实例的方法
*
* @param resultSet 结果集
* @return 结果集的封装对象
*/
public static ResultSetEnhancer getInstance(ResultSet resultSet) {
return new ResultSetEnhancer(resultSet);
}
/**
* 获取指定行的数据
*
* @param columnIndex 数据库行号(从1开始)
* @return 数据库列名(key)/列值(value)集合
*/
public Map<String, Object> getRowDataByRowIndex(int rowIndex) {
return resultList.get(ensureNotOutOffIndex(rowIndex) - 1);
}
/**
* 获取指定索引区间[fromIndex,toIndex)上的值
*
* @param fromIndex 起始索引 从1开始
* @param toIndex 结束索引
* @return 行数据集合
*/
public List<Map<String, Object>> getRowDatas(int fromIndex, int toIndex) {
return resultList.subList(fromIndex - 1, toIndex - 1);
}
/**
* 从指定位置开始获取指定数量的数据
*
* @param startIndex 起始索引 从1开始
* @param size 截取数量
* @return 行数据集合
*/
public List<Map<String, Object>> getRowDatasWithSize(int startIndex, int size) {
return resultList.subList(startIndex - 1, startIndex - 1 + size);
}
/**
* 获取数据库指定列的数据
*
* @param columnLabel 数据库列名
* @return 该列所有值的列表
*/
public List<Object> getColumnDataByColumnLabel(String columnLabel) {
List<Object> columnValueList = new ArrayList<Object>();
for (Map<String, Object> temp : resultList) {
columnValueList.add(temp.get(deletUnderLineAndToLowerCase(columnLabel)));
}
return columnValueList;
}
/**
* 将数据的一行转换成指定的类
*
* @param <T>
* @param rowIndex 数据库行索引
* @param clazz 该类的字段必须有标准化的set方法
* @param flage 是否使用下划线转驼峰
* @return 对象
*/
public <T> T getBeanByRowIndex(int rowIndex, Class<T> clazz) {
Map<String, Object> temp = getRowDataByRowIndex(rowIndex); // 获取指定行的map数据
return mapToBean(temp, clazz);
}
/**
* 指定行索引区域的值转换为指定对象的列表
*
* @param <E>
* @param fromIndex 起始索引 从1开始
* @param toIndex 结束索引
* @param clazz 指定类的Class
* @return 对象列表
*/
public <E> List<E> getBeanList(int fromIndex, int toIndex, Class<E> clazz) {
List<Map<String, Object>> tempList = getRowDatas(fromIndex, toIndex);
List<E> relult = new ArrayList<E>();
if (tempList != null) {
for (Map<String, Object> temp : tempList) {
relult.add(mapToBean(temp, clazz));
}
}
return relult;
}
/**
* 从指定位置开始获取指定数量的数据,封装为指定对象的列表
*
* @param <E>
* @param startIndex 起始索引 从1开始
* @param size 截取数量
* @param clazz 指定类的Class
* @return 对象列表
*/
public <E> List<E> getBeanListWithSize(int startIndex, int size, Class<E> clazz) {
List<Map<String, Object>> tempList = getRowDatasWithSize(startIndex, size);
List<E> relult = new ArrayList<E>();
if (relult != null) {
for (Map<String, Object> temp : tempList) {
relult.add(mapToBean(temp, clazz));
}
}
return relult;
}
/**
* 将全部数据封装成指定对象的列表集合返回
*
* @param <E>
* @param startIndex 起始索引 从1开始
* @param size 截取数量
* @param clazz 指定类的Class
* @return 对象列表
*/
public <E> List<E> getBeanAll(Class<E> clazz) {
List<E> relult = new ArrayList<E>();
if (resultList != null) {
for (Map<String, Object> temp : resultList) {
relult.add(mapToBean(temp, clazz));
}
}
return relult;
}
/**
* Map转换成Bean
*
* @param <T>
* @param map
* @param clazz
* @return
*/
private <T> T mapToBean(Map<String, Object> map, Class<T> clazz) {
Field[] fileds = clazz.getDeclaredFields();// 不包含父类字段
if (fileds.length > 0) {
String[] filedNames = new String[fileds.length];// 存储字段名
for (int i = 0; i < fileds.length; i++) {
filedNames[i] = fileds[i].getName();
}
if (map != null) {
try {
T bean = clazz.newInstance();
for (int i = 0; i < fileds.length; i++) {
String filedName = filedNames[i];
Method setter = clazz.getMethod("set" + firstUpperCase(filedName), fileds[i].getType());
Object param = map.get(filedName.toLowerCase());
setter.invoke(bean, param);
}
return bean;
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
/**
* 首字母变大写
*
* @param str
* @return
*/
public static String firstUpperCase(String str) {
if (Character.isUpperCase(str.charAt(0)))
return str;
else
return (new StringBuilder()).append(Character.toUpperCase(str.charAt(0))).append(str.substring(1))
.toString();
}
/**
* 转换为下划线
*
* @param camelCaseName
* @return
*/
public static String underscoreName(String camelCaseName) {
StringBuilder result = new StringBuilder();
if (camelCaseName != null && camelCaseName.length() > 0) {
result.append(camelCaseName.substring(0, 1).toLowerCase());
for (int i = 1; i < camelCaseName.length(); i++) {
char ch = camelCaseName.charAt(i);
if (Character.isUpperCase(ch)) {
result.append("_");
result.append(Character.toLowerCase(ch));
} else {
result.append(ch);
}
}
}
return result.toString();
}
/**
* 转换为驼峰
*
* @param underscoreName
* @return
*/
public static String camelCaseName(String underscoreName) {
if (underscoreName.contains("_")) {
StringBuilder result = new StringBuilder();
if (underscoreName != null && underscoreName.length() > 0) {
boolean flag = false;
for (int i = 0; i < underscoreName.length(); i++) {
char ch = underscoreName.charAt(i);
if ("_".charAt(0) == ch) {
flag = true;
} else {
if (flag) {
result.append(Character.toUpperCase(ch));
flag = false;
} else {
result.append(ch);
}
}
}
}
return result.toString();
} else {
return underscoreName;
}
}
/**
* 去掉下划线转为小写
*
* @param str
* @return
*/
private static String deletUnderLineAndToLowerCase(String str) {
return str.replaceAll("_", "").toLowerCase();
}
/**
* 修正索引,保证索引不越界
*
* @param index
* @return
*/
private int ensureNotOutOffIndex(int index) {
if (index < 1) {
index = 1;
}
if (index > rowCount) {
index = rowCount;
}
return index;
}
}
ResultSet通用处理类------转换为包含Map的List集合实现数据检索(第一版)
最新推荐文章于 2022-06-02 09:58:18 发布