之前写过一个JDBC通用的DAO工具类,感觉不完美的地方是用到了第三方的BeanUtils的jar包,那就没什么意思了。现在改进一下,模拟一个Spring的JdbcTemplate工具类。使用的时候,传入一个数据源就可以了。
import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* JDBC工具类
*/
public class JdbcTemplate {
private DataSource dataSource;
//通过构造方法传入数据源对象
public JdbcTemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 获取连接对象的方法
*/
public Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
/**
* 增删改的通用方法
* @param sql SQL语句
* @param param 替换占位符的真实值,可变参数在方法中是一个数组,数组索引从0开始
* @return 影响的行数
*/
public int update(String sql, Object... param) {
Connection connection = null;
PreparedStatement ps = null;
//影响的行数
int row = 0;
try {
//1.获取连接对象
connection = getConnection();
//2.创建预编译的语句对象,提供SQL语句,并且有占位符
ps = connection.prepareStatement(sql);
//3.替换占位符为真实的数据
//3.1 获取参数元数据对象
ParameterMetaData parameterMetaData = ps.getParameterMetaData();
//3.2 通过参数元数据获取占位符的个数
int count = parameterMetaData.getParameterCount();
//3.3 给每个占位符赋值
for (int i = 0; i < count; i++) {
ps.setObject(i + 1, param[i]);
}
//4.执行增删改操作
row = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.释放资源
close(connection, ps);
}
return row;
}
/**
* 通用的查询方法
* @param sql SQL语句
* @param clazz 要封装的每个元素的类型,如:Student.class Account.class
* @param param 替换占位符的真实值
*
*/
public <T> List<T> query(String sql, Class<T> clazz, Object...param) {
//0.创建一个集合对象
List<T> list = new ArrayList<>();
Connection connection = null;
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
//1.创建连接对象
connection = getConnection();
//2.创建预编译的语句对象,提供SQL语句
ps = connection.prepareStatement(sql);
//3.替换占位符
//3.1 获取参数元数据对象
ParameterMetaData parameterMetaData = ps.getParameterMetaData();
//3.2 通过参数元数据获取占位符的个数
int count = parameterMetaData.getParameterCount();
//3.3 给每个占位符赋值
for (int i = 0; i < count; i++) {
ps.setObject(i + 1, param[i]);
}
//4.执行SQL语句
resultSet = ps.executeQuery();
//获取结果集元数据
ResultSetMetaData metaData = resultSet.getMetaData();
//获取总列数
int columnCount = metaData.getColumnCount();
//5.得到结果集,遍历结果集,封装成List对象
while (resultSet.next()) {
//每次遍历创建一个对象进行封装,获取无参的构造方法,再进行实例化
T obj = clazz.getConstructor().newInstance();
//循环给每个属性赋值
for (int i = 1; i <= columnCount; i++) {
//获取这一列的名字,与类中成员变量名字是一样的
String columnName = metaData.getColumnName(i);
//从结果集中取出这一列的值
Object value = resultSet.getObject(columnName);
//通过名字获取相应的属性对象
Field field = clazz.getDeclaredField(columnName);
//设置为暴力反射
field.setAccessible(true);
//给属性赋值,参数1:要赋值的对象,参数2:要赋的值
field.set(obj, value);
}
//添加到集合中
list.add(obj);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//6.释放资源
close(connection, ps, resultSet);
}
//返回集合对象
return list;
}
/**
* 编写释放资源的方法
* @param connection 连接对象
* @param statement 语句对象
* @param resultSet 结果集
*/
public void close(Connection connection, Statement statement, ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 编写释放资源的方法
* @param connection 连接对象
* @param statement 语句对象
*/
public void close(Connection connection, Statement statement) {
close(connection, statement, null);
}
}
版权声明:本文为nlcold原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。