9.30JavaWeb之PreparedStatement获取任意一个对象的属性值
作者:互联网
9.30JavaWeb之PreparedStatement获取任意一个对象的属性值
获取一个对象的属性值
关键点:
-
使用泛型方法来获取
-
通过泛型的模式获取运行时类
-
/*通过反射获取运行是要建立的类的引用*/
/**
* 建立泛型参数、泛型方法
* <T>表示泛型方法
* 方法名前面的T表示返回值类型
* Class<T>当中的T表示对应的运行时类
* @param clazz
* @param sql
* @param args
* @param <T>
* @return
*/
public <T> T getInstance(Class<T> clazz, String sql, Object ...args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//获取数据库连接
conn = JDBCUtils.getConnection();
//预编译sql
ps = conn.prepareStatement(sql);
//填充占位符
for (int i=0; i<args.length; i++) {
ps.setObject(i+1, args[i]);
}
//执行sql保存为结果集对象
rs = ps.executeQuery();
//获取结果集元数据
ResultSetMetaData rsmd = rs.getMetaData();
//获取列数
int columnCount = rsmd.getColumnCount();
//获取结果集
if (rs.next()) {
//通过反射获取运行时加载类建立对象的引用--->反射+泛型
T t = clazz.newInstance(); //--->任何一个类在提供一个JavaBean对象的时候要提供一个空参的public权限的构造器,在这里使用
/*
方法当中返回一个t
t由当前类决定的
*/
//动态的获取列,列的数量为列数
for (int j=0; j<columnCount; j++) {
//动态的获取列值--->结果集当中获取列值
Object columnValue = rs.getObject(j+1);
//获取每列的列名
String columnLabel = rsmd.getColumnLabel(j+1);
//动态获取加载的类的属性--->获取到域(T类型的)
Field field = clazz.getField(columnLabel);
//设置私有属性可访问
field.setAccessible(true);
//将对象属性设置成列值
field.set(t, columnValue);
}
return t;
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
获取集合对象(多个对象)的属性值
查询结果集返回多条数据--->多个对象
新语法糖:--->list.forEach(System.out::println)
由于占位符的使用所以解决了SQL
注入的问题
/**
* 查询一条sql语句返回多个结果集对象
* 使用List进行封装然后再集中展示
* @since JDK 1.8
* @date 2021/09/30
* @author Lucifer
*/
public <T> List<T> getForList(Class<T> clazz, String sql, Object ...args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//获取数据库连接
conn = JDBCUtils.getConnection();
//预编译sql
ps = conn.prepareStatement(sql);
//填充占位符
for (int i=0; i<args.length; i++) {
ps.setObject(i+1, args[i]);
}
//执行sql保存为结果集对象
rs = ps.executeQuery();
//获取结果集元数据
ResultSetMetaData rsmd = rs.getMetaData();
//获取列数
int columnCount = rsmd.getColumnCount();
//创建集合对象--->用于存储查询出的结果集对象
ArrayList<T> list = new ArrayList<T>();
//查询多条语句使用循环进行查询
while (rs.next()) {
T t = clazz.newInstance();
//处理结果集每一行数据的每一列
for (int j=0; j<columnCount; j++) {
//获取列值
Object columnValue = rs.getObject(j+1);
//获取列名
String columnLabel = rsmd.getColumnLabel(j+1);
//动态获取运行类
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columnValue);
}
//将t对象添加进入集合数组
list.add(t);
/*
查询未找到
1、抛异常了
2、没有数据了
*/
}
return list;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
注意:
-
占位符的目的是为了解决
SQL
注入问题 -
避免拼串的发生
/**
* 针对所有得运行时类进行表的查询操作
* @since JDK 1.8
* @date 2021/09/30
* @author Lucifer
*/
public <T> T getInstanceSQL(Class<T> clazz, String sql, Object ...args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//建立连接
conn = JDBCUtils.getConnection();
//预编译sql
ps = conn.prepareStatement(sql);
//填充占位符
for (int i=0; i<args.length; i++) {
ps.setObject(i+1, args[i]);
}
//执行查询操作
rs = ps.executeQuery();
//获取结果集元数据
ResultSetMetaData rsmd = rs.getMetaData();
//通过结果集元数据获取列数
int columnCount = rsmd.getColumnCount();
//查询表中第一行数据
while (rs.next()) {
//通过反射获取运行时加载类建立对象的引用--->反射+泛型
T t = clazz.newInstance();
//循环获取列值
for (int j=0; j<columnCount; j++) {
//动态的获取列值--->结果集当中获取列值
Object columnValue = rs.getObject(j+1);
//获取每列的列名
String columnLabel = rsmd.getColumnLabel(j+1);
//动态获取加载的类的属性--->获取到域(T类型的)
Field field = clazz.getField(columnLabel);
//设置私有属性可访问
field.setAccessible(true);
//将对象属性设置成列值
field.set(t, columnValue);
}
return t;
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
测试方法:
@Test
public void testLoginNo1() {
//获取控制台内容
Scanner scan = new Scanner(System.in);
System.out.println("UserName:");
String user = scan.next();
System.out.println("PassWord:");
String password = scan.next();
//提供一个sql语句
String sql = "select `name`, `password` from users where Name = ? and Password = ?";
/*
上诉的写法称为拼串,需要拼写sql语句。--->不是一个完整的sql语句,存在sql注入的风险
*/
User returnUser = getInstanceSQL(User.class, sql, user, password);
if (returnUser!=null){
System.out.println("Successfully!");
}else {
System.out.println("UserName or PassWord Error!!!");
}
}
Preparestatement
预编译sql
语句--->预编译期间已经判断了sql
的逻辑关系
Preparestatement
可以传流文件,拼串不可以。
Preparestatement
可以更高效的插入--->预编译期间只需要检验一次,后续的添加只需要填充占位符即可
Statement
因为没有预编译,所以在拼串的时候可以改变其逻辑关系,由且变成或等
小结
面向接口编程的思想
ORM
思想
只需要面向JDBC接口编程
原则:
-
不出现第三方的API
-
将第三方API与代码解耦,第三方API封装到
XML
或者配置文件中,全程操作使用Driver
对象进行操作--->多态的一种形式
一个JavaBean
类对应到数据库当中的一张表
原则:
-
Java
操作的任何东西都是以对象的方式进行呈现-
getColumnCount
-
getColumnLabel
-
使用反射获取到运行时类进行加载获取属性
//动态获取加载的类的属性--->获取到域(T类型的)
Field field = clazz.getField(columnLabel);
//设置私有属性可访问
field.setAccessible(true);
//将对象属性设置成列值
field.set(t, columnValue);
标签:9.30,ps,PreparedStatement,JavaWeb,rs,---,获取,sql,null 来源: https://www.cnblogs.com/JunkingBoy/p/15369371.html