在进行JDBC封装成工具类的时候,增删改可以直接进行封装,但是查询不可以,因为不同的SQL语句查询出的结果是不同的,所以Result结果集中的内容和类型都是不确定的,所以要进行特殊的封装
第一种方式
使用RowMapper接口,在其中定义一个将结果集转换成对象的方法,最终将转换后的对象都添加进集合中返回
public interface RowMapper<T> {
T getRow(ResultSet resultSet);
}
泛型类类型是Student类型,我们每查询一次就需要创建一个特定类型的方法,将结果集封装成对象
public class StudentRowMapper implements RowMapper<Student> {
@Override
public Student getRow(ResultSet resultSet) {
try {
int sid = resultSet.getInt("sid");
String sname = resultSet.getString("sname");
int sage = resultSet.getInt("sage");
return new Student(sid, sname, sage);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
而这个查询的方法是公共的,不需要更改
/**
* 查询
* @param mapper 封装接口
* @param sql sql语句
* @param params sql语句参数
* @param <T> 封装对象类型
* @return 对象集合
*/
public static <T> List<T> executeQuery(RowMapper<T> mapper, String sql, Object...params) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = getConnection();
preparedStatement = connection.prepareStatement(sql);
if (params != null) {
for(int i = 0; i < params.length; i++) {
preparedStatement.setObject(i + 1, params[i]);
}
}
resultSet = preparedStatement.executeQuery();
// 把ResultSet封装成Java对象
ArrayList<T> arrayList = new ArrayList<>();
while (resultSet.next()) {
T t = mapper.getRow(resultSet);
if (t != null) {
arrayList.add(t);
}
}
return arrayList;
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
close(resultSet, preparedStatement, connection);
}
return null;
}
第二种方法
使用反射+内省
先获取到结果集中每列的名字,然后用反射根据列名去实体类中找到对应的属性,并为其赋值,都赋值之后就封装成一个对象,添加到集合中
public static <T> List<T> executeQuery2(Class<T> tClass, String sql, Object[] params) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = getConnection();
preparedStatement = connection.prepareStatement(sql);
for(int i = 0; i < params.length; i++) {
preparedStatement.setObject(i + 1, params[i]);
}
resultSet = preparedStatement.executeQuery();
// 获取结果集的所有字段名
ResultSetMetaData metaData = resultSet.getMetaData();
List<T> list = new ArrayList<>();
while (resultSet.next()) {
T t = tClass.newInstance();
// 遍历所有的列,为其赋值
for(int i = 0; i < metaData.getColumnCount(); i++) {
// 获取每列的名称
String columnLabel = metaData.getColumnLabel(i + 1);
try {
// 根据列名找到实体类中对应的属性
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnLabel, tClass);
// 为属性赋值,封装成对象
if (propertyDescriptor != null) {
Method writeMethod = propertyDescriptor.getWriteMethod();
writeMethod.invoke(t, resultSet.getObject(columnLabel));
}
} catch (IntrospectionException | InvocationTargetException e) {
e.printStackTrace();
}
}
list.add(t);
}
return list;
} catch (SQLException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
} finally {
close(resultSet, preparedStatement, connection);
}
return null;
}