手动实现查询结果返回为一个对象集合

实体类

package com.jdbc;

public class User {
private Integer id;
private String name;
private Integer age; @Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}

反射工具类

package com.jdbc;

import java.lang.reflect.*;

/**
* 反射工具类,访问私有变量, 获取泛型类型 Class, 提取集合中元素属性等 Utils 函数
*/
public class ReflectionUtils { /**
* 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型
* 如: public EmployeeDao extends BaseDao<Employee, String>
*/
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(Class clazz, int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
return Object.class;
}
if (!(params[index] instanceof Class)) {
return Object.class;
}
return (Class) params[index];
} /**
* 通过反射, 获得 Class 定义中声明的父类的泛型参数类型
* 如: public EmployeeDao extends BaseDao<Employee, String>
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> getSuperGenericType(Class clazz) {
return getSuperClassGenricType(clazz, 0);
} /**
* 循环向上转型, 获取对象的 DeclaredMethod
*/
public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes) {
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
//superClass.getMethod(methodName, parameterTypes);
return superClass.getDeclaredMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
//Method 不在当前类定义, 继续向上转型
}
}
return null;
} /**
* 使 filed 变为可访问
*/
public static void makeAccessible(Field field) {
if (!Modifier.isPublic(field.getModifiers())) {
field.setAccessible(true);
}
} /**
* 循环向上转型, 获取对象的 DeclaredField
*/
public static Field getDeclaredField(Object object, String filedName) {
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
return superClass.getDeclaredField(filedName);
} catch (NoSuchFieldException e) {
//Field 不在当前类定义, 继续向上转型
}
}
return null;
} /**
* 直接调用对象方法, 忽略修饰符(private, protected)
*/
public static Object invokeMethod(Object object, String methodName, Class<?>[] parameterTypes, Object[] parameters) throws InvocationTargetException {
Method method = getDeclaredMethod(object, methodName, parameterTypes);
if (method == null) {
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
}
method.setAccessible(true);
try {
return method.invoke(object, parameters);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
} /**
* 直接设置对象属性值, 忽略 private/protected 修饰符与 setter
*/
public static void setFieldValue(Object object, String fieldName, Object value) {
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
makeAccessible(field);
try {
field.set(object, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} /**
* 直接读取对象的属性值, 忽略 private/protected 修饰符与 setter
*/
public static Object getFieldValue(Object object, String fieldName) {
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
makeAccessible(field);
Object result = null;
try {
result = field.get(object);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return result;
}
}

测试

package test.jdbc;

import com.jdbc.ReflectionUtils;
import com.jdbc.User;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import java.io.InputStream;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties; public class JDBCResultObject {
private Connection conn;
private ResultSet resultSet; @BeforeEach
public void start() throws Exception {
Properties properties = new Properties();
InputStream in = this.getClass().getClassLoader().getResourceAsStream("jdbc.properties");
properties.load(in); String driver = properties.getProperty("driver");
String jdbcUrl = properties.getProperty("jdbcUrl");
String user = properties.getProperty("user");
String password = properties.getProperty("password"); Class.forName(driver); conn = DriverManager.getConnection(jdbcUrl, user, password);
} @AfterEach
public void end() throws Exception {
if (resultSet != null) {
resultSet.close();
}
if (conn != null) {
conn.close();
}
} @Test
public void testResultSetOfObject() {
ResultSetMetaData(User.class, "SELECT * FROM user where id > ?", 0);
} public <T> void ResultSetMetaData(T t, String sql, Object... args) {
try {
PreparedStatement preparedStatement = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
resultSet = preparedStatement.executeQuery();
// 得到 ResultSetMetaData 对象
ResultSetMetaData rsmd = resultSet.getMetaData(); // 封装结果集
List<T> resultList = new ArrayList<>(100);
T object = null;
while (resultSet.next()) {
object = (T) ((Class) t).newInstance();
for (int i = 0; i < rsmd.getColumnCount(); i++) {
String columnLabel = rsmd.getColumnLabel(i + 1);
Object columnValue = resultSet.getObject(columnLabel);
ReflectionUtils.setFieldValue(object, columnLabel, columnValue);
}
resultList.add(object);
} System.out.println(resultList);
} catch (Exception e) {
e.printStackTrace();
}
}
}

JDBC-通用查询的更多相关文章

  1. 利用反射及JDBC元数据编写通用查询方法

    元数据:描述数据的数据,ResultSetMetaData是描述ResultSet的元数据对象,从它可以得到数据集有多少了,每一列的列名... ResultSetMetaData可以通过ResultS ...

  2. JDBC的通用查询的方法

    PreparedStatement 1.Why 1):使用Statement需要进行拼写SQL语句,很辛苦,而且容易出错. 2):使用Statement可以发生SQL注入. SQl注入: SQL注入是 ...

  3. <五>JDBC_利用反射及JDBC元数据编写通用的查询方法

    此类针对javaBean类写了一个通用的查询方法,List<javaBean> 通用查询更新中...:通过学习,深刻体会到学会反射就等于掌握了java基础的半壁江山! 一.使用JDBC驱动 ...

  4. 【转】JDBC为什么要使用PreparedStatement而不是Statement

    http://www.importnew.com/5006.html PreparedStatement是用来执行SQL查询语句的API之一,Java提供了 Statement.PreparedSta ...

  5. 【JDBC】预编译SQL与防注入式攻击

    在JDBC编程中,常用Statement.PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedS ...

  6. 初学JDBC的一些总结(二)

    一.简单介绍PreparedStatement 和Statement的区别: PreparedStatement是用来执行SQL查询语句的API之一,Java提供了 Statement.Prepare ...

  7. Hibernate 离线对象构建通用查询

    1.业务场景 当下主系统衍生子业务系统已经成为常态,像京东的物流和金融,阿里的支付宝和淘宝. 子业务系统需要对主系统的资源进行访问,这里的资源我具体化为数据库数据,但日常业务中可能不只是数据. 抽象服 ...

  8. JDBC 中preparedStatement和Statement区别

    一.概念 PreparedStatement是用来执行SQL查询语句的API之一,Java提供了 Statement.PreparedStatement 和 CallableStatement三种方式 ...

  9. Jdbc -Statement

    Java提供了 Statement.PreparedStatement 和 CallableStatement三种方式来执行查询语句: PreparedStatement是用于执行参数化查询 预编译s ...

  10. JDBC编程之预编译SQL与防注入式攻击以及PreparedStatement的使用教程

      转载请注明原文地址: http://www.cnblogs.com/ygj0930/p/5876951.html 在JDBC编程中,常用Statement.PreparedStatement 和  ...

随机推荐

  1. Tomcat启动失败

    前景:使用的是tomcat9.0,配置好后,使用一切正常,刷慕课跟着做练习,也一切正常.出事在于,老师为了方便直接拷之前写的一个项目,我照做了,老师改了虚拟路径了,我忘记改了,然后跑了一下项目就出毛病 ...

  2. SyntaxHighlighter行号显示错误问题解决方案

    SyntaxHighlighter是根据代码中的换行符分配行号的.但是,如果一行代码或者注释比较长,在页面显示时需要分成多行显示,会出现行号对不上的问题,像这样: 通过设置CSS强制不换行,可以保证行 ...

  3. PLSQL 使用技巧汇总贴(一个坑)

    PLSQL是一款非常强大的工具, 只不过自己不会使用.. 1.记住密码: 首先 工具->首选项 打开 在 oracle 选项下的 登录 历史  定义 带密码存储--勾选 2. 关键字高亮 -- ...

  4. [资源]--IOS捷径大全,众多实用小功能

    一.实用工具 1.支付助手3.0(新) (扫一扫.微信扫码.微信收款.支付宝扫码.Apple Pay.AA付款.查快递.蚂蚁森林.蚂蚁庄园.彩票.股票.运动.淘票票.乘车码.生活缴费.火车票等等): ...

  5. HDU-5373-水题-卡常数时间

    姿势就是力量啊! 第一次意识到long long 比 int要慢很多.当时想到了各种优化仍然TLE,最后也没A出来,就是用了long long #include <cstdio> #inc ...

  6. 如何修改可运行Jar包,如何反编译Jar包

    将可运行Jar包,反编译成项目,修改代码,再次编译,打包. 需要工具:jd-gui.myeclipse 具体步骤: 1.使用jd-gui打开原始的Jar包,选择File-->Save All  ...

  7. luogu3195/bzoj1010 玩具装箱(斜率优化dp)

    推出来式子然后斜率优化水过去就完事了 #include<cstdio> #include<cstring> #include<algorithm> #include ...

  8. A1001. A+B Format

    Calculate a + b and output the sum in standard format -- that is, the digits must be separated into ...

  9. A1071. Speech Patterns

    People often have a preference among synonyms of the same word. For example, some may prefer "t ...

  10. 【模板】堆优化Dijkstra

    Dij的核心思想:全局最小值不会被其他节点更新,因此得到最小值后只需要扩展一次即可. 概念:扩展.出队 注意:vis[ ]数组表示的是每个节点是否扩展过,因此开始时vis[st]不置1. 时间复杂度\ ...