ResultSet通用处理类------转换为包含Map的List集合实现数据检索(第一版)

博客介绍了ResultSet通用处理类,通过将其转换为包含Map的List集合,实现数据检索功能。这一方法在数据处理和检索方面具有重要作用,能有效提升数据处理效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豢龙先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值