一、前言
本文提供提供一套JDBC流式查询的工具类。
二、
当遇到大数据量数据读取时,jdbc的流式读取可以提高一定的查询速度,对内存占用的优化比较明显。
/**
* JDBC读取数据功能(普通/流式)
* @param url 数据库地址
* @param username 数据库用户名
* @param password 数据库密码
* @param sql 执行语句
* @param clazz 结果集类型
* @param off 流式查询(true/开,false/关)
* @param size 每次读取条数
* */
public static List readResult(String url, String username, String password, String sql, Class clazz, boolean off, int size){
Connection conn = null;
ResultSet rs = null;
try {
//获得数据库驱动的Class对象
//数据库版本在6.0以上的用(com.mysql.cj.jdbc.Driver)
Class.forName("com.mysql.jdbc.Driver");
//连接数据库
conn = DriverManager.getConnection(url,username,password);
PreparedStatement preparedStatement = null;
if (off){
//JDBC预编译
preparedStatement = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
//一次性获取多少行数据
preparedStatement.setFetchSize(size);
preparedStatement.setFetchDirection(ResultSet.FETCH_REVERSE);
}else{
//JDBC预编译
preparedStatement = conn.prepareStatement(sql);
}
rs = preparedStatement.executeQuery();
//获取结果集的源数据
ResultSetMetaData metaData = rs.getMetaData();
//获取结果集列数
int columnCount = metaData.getColumnCount();
List list = new ArrayList<>();
while (rs.next()){
T t = clazz.newInstance();
for (int i = 0;i
因为是用反射方法获取的实体类参数,所以需要对jdbc读取的字段名进行驼峰处理,这里再提供一个工具类
/**
* 参数名驼峰式命名
* @param srcStr 参数名
*/
public static String firstCharacterToUpper(String srcStr) {
if (StringUtils.isBlank(srcStr)){
return srcStr;
}
StringBuilder sbf = new StringBuilder();
String[] split = srcStr.split("_");
for (int i = 0, index = split.length; i < index; i++){
if (i == 0){
sbf.append(split[i]);
}else{
String s = split[i].substring(0, 1).toUpperCase() + split[i].substring(1);
sbf.append(s);
}
}
return sbf.toString();
}
测试类传参示例:
@Test
public void jdbcSelect(){
long startTime = System.currentTimeMillis();
List userList = JdbcUtils.readResult(druidDatabaseDefinition.getUrl(),druidDatabaseDefinition.getUsername(),druidDatabaseDefinition.getPassword(),"select * from t_user", UserJdbc.class,true,2000);
System.out.println("消耗时间:"+(System.currentTimeMillis()-startTime)/1000+"秒");
System.out.println("查询结果:"+userList.size()+"条");
}
工具类:
public class jdbcUtil {
/**
* JDBC读取数据功能(普通/流式)
* @param className 数据库驱动
* @param url 数据库地址
* @param username 数据库用户名
* @param password 数据库密码
* @param sql 执行语句
* @param off 流式查询(true/开,false/关)
* @param size 每次读取条数
* */
public static List readResult(String className, String url, String username, String password, String sql, Class clazz, boolean off, Integer size){
Connection conn = null;
ResultSet rs = null;
try {
//获得数据库驱动的Class对象
//数据库版本在6.0以上的用(com.mysql.cj.jdbc.Driver)
Class.forName(className);
//连接数据库
conn = DriverManager.getConnection(url,username,password);
PreparedStatement preparedStatement = null;
if (off){
//JDBC预编译
preparedStatement = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
if (ObjectUtils.isEmpty(size)){
size = 5000;
}
//一次性获取多少行数据
preparedStatement.setFetchSize(size);
preparedStatement.setFetchDirection(ResultSet.FETCH_REVERSE);
}else{
//JDBC预编译
preparedStatement = conn.prepareStatement(sql);
}
rs = preparedStatement.executeQuery();
//获取结果集的源数据
ResultSetMetaData metaData = rs.getMetaData();
//获取结果集列数
int columnCount = metaData.getColumnCount();
List list = new ArrayList<>();
//获取对象中所有字段名
HashMap variateMap = new HashMap<>();
Field[] declaredFields =clazz.getDeclaredFields();
for (Field declaredField : declaredFields){
variateMap.put(declaredField.getName(),declaredField);
}
while (rs.next()){
T t = clazz.newInstance();
for (int i = 0;i
三、结尾
有不足的地方大家尽管指出,学无止境。也希望这篇文章可以帮到有需要的小伙伴。