目录
01_分析jdbc中操作问题-抽取增删改方法的通用方法
1.1、DBAssit.java
package com.itheima.dbassit;
import com.itheima.handler.ResultSetHandler;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* 封装的工具类
*/
public class DBAssit {
private DataSource dataSource;
public DBAssit(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 执行增删改的方法
*
* @param sql
* @param params
* @return
*/
public int update(String sql, Object... params) {
Connection conn = null;
PreparedStatement pstm = null;
try {
//1.得到连接
conn = dataSource.getConnection();
//2.使用连接和参数的sql语句创建预处理对象
pstm = conn.prepareStatement(sql);
//3.得到sql语句参数的源信息(有几个参数,都什么类型等等)
ParameterMetaData pmd = pstm.getParameterMetaData();
//4.判断语句中参数的个数和方法参数params的个数是否一致,不一致肯定没法执行
int parameterCount = pmd.getParameterCount();//参数的个数(问号的个数)
if (parameterCount > 0) {
if (params == null) {
throw new NullPointerException("没有sql语句执行必须的参数");
}
if (params.length != parameterCount) {
throw new RuntimeException("传入的参数个数和语句所需的参数个数不一致,语句无法执行");
}
}
//5.给sql语句的参数赋值
for (int i = 0; i < parameterCount; i++) {
pstm.setObject(i + 1, params[i]);
}
//6.执行语句
int res = pstm.executeUpdate();
//7.返回执行结果
return res;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
release(conn, pstm, null);
}
}
public Object query(String sql, ResultSetHandler rsh, Object... params) {
Connection conn = null;
PreparedStatement pstm = null;
ResultSet rs = null;
try {
//1.得到连接
conn = dataSource.getConnection();
//2.使用连接和参数的sql语句创建预处理对象
pstm = conn.prepareStatement(sql);
//3.得到sql语句参数的源信息(有几个参数,都什么类型等等)
ParameterMetaData pmd = pstm.getParameterMetaData();
//4.判断语句中参数的个数和方法参数params的个数是否一致,不一致肯定没法执行
int parameterCount = pmd.getParameterCount();//参数的个数(问号的个数)
if (parameterCount > 0) {
if (params == null) {
throw new NullPointerException("没有sql语句执行必须的参数");
}
if (params.length != parameterCount) {
throw new RuntimeException("传入的参数个数和语句所需的参数个数不一致,语句无法执行");
}
}
//5.给sql语句的参数赋值
for (int i = 0; i < parameterCount; i++) {
pstm.setObject(i + 1, params[i]);
}
//6.执行语句
rs = pstm.executeQuery();
//7.返回执行结果
return rsh.handle(rs);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
release(conn, pstm, rs);
}
}
private void release(Connection conn, PreparedStatement pstm, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (pstm != null) {
try {
pstm.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
02_抽取查询方法-编写封装一个实体对象的结果集处理器
2.1、BeanHandler.java
package com.itheima.handler.impl;
import com.itheima.handler.ResultSetHandler;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
/**
* 结果集封装的具体实现类。
* 此类实现的是把一个结果集rs的内容封装到一个指定的实体类对象中
* 使用要求:实体类中的属性必须和表中的列名一致(sql语句查询出来的列名一致)
*
* @param <T>
*/
public class BeanHandler implements ResultSetHandler {
private Class domainClass;
public BeanHandler(Class domainClass) {
this.domainClass = domainClass;
}
/**
* 把rs的内容封装到domainClass所表示的类中
*
* @param rs
* @return
*/
@Override
public Object handle(ResultSet rs) {
try {
//1.创建一个实体类对象
Object bean = domainClass.newInstance();
//2.判断是否有结果集
if (rs.next()) {
//3.得到结果集rs中所有的列名
//要想得到列名,得先得到结果集的源信息
ResultSetMetaData rsmd = rs.getMetaData();
//得到源信息之后,还要得到有多少列
int columnCount = rsmd.getColumnCount();
//遍历列数
for (int i = 1; i <= columnCount; i++) {
//得到每列的名称
String columnName = rsmd.getColumnName(i);
//列名其实就是实体类的属性名称,于是就可以使用列名得到实体类中属性的描述器
PropertyDescriptor pd = new PropertyDescriptor(columnName, domainClass);//实体类中定义的私有类成员和它的get以及set方法
//获取属性的写入方法(set方法)
Method method = pd.getWriteMethod();
//获取当前列名所对应的值
Object columnValue = rs.getObject(columnName);
//通过执行写方法把得到的值给属性赋上
method.invoke(bean, columnValue);
}
}
//4.返回
return bean;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}