为什么报错空指针异常?
BaseDao
package com.atguigu.schedule.dao;
import com.atguigu.schedule.util.JDBCUtil;
import java.lang.reflect.Field;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
public class BaseDao {
// 公共的查询方法 返回的是单个对象
public <T> T baseQueryObject(Class<T> clazz, String sql, Object ... args) {
T t = null;
Connection connection = JDBCUtil.getConnection();
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
int rows = 0;
try {
// 准备语句对象
preparedStatement = connection.prepareStatement(sql);
// 设置语句上的参数
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
// 执行 查询
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
t = (T) resultSet.getObject(1);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != resultSet) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != preparedStatement) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
JDBCUtil.releaseConnection();
}
return t;
}
// 公共的查询方法 返回的是对象的集合
public <T> List<T> baseQuery(Class clazz, String sql, Object ... args){
List<T> list =new ArrayList<>();
Connection connection = JDBCUtil.getConnection();
PreparedStatement preparedStatement=null;
ResultSet resultSet =null;
int rows = 0;
try {
// 准备语句对象
preparedStatement = connection.prepareStatement(sql);
// 设置语句上的参数
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i+1,args[i]);
}
// 执行 查询
resultSet = preparedStatement.executeQuery();
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
// 将结果集通过反射封装成实体类对象
while (resultSet.next()) {
// 使用反射实例化对象
Object obj =clazz.getDeclaredConstructor().newInstance();
for (int i = 1; i <= columnCount; i++) {
String columnName = metaData.getColumnLabel(i);
Object value = resultSet.getObject(columnName);
// 处理datetime类型字段和java.util.Data转换问题
if(value.getClass().equals(LocalDateTime.class)){
value= Timestamp.valueOf((LocalDateTime) value);
}
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(obj,value);
}
list.add((T)obj);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null !=resultSet) {
try {
resultSet.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (null != preparedStatement) {
try {
preparedStatement.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
JDBCUtil.releaseConnection();
}
return list;
}
// 通用的增删改方法
public int baseUpdate(String sql,Object ... args) {
// 获取连接
Connection connection = JDBCUtil.getConnection();
PreparedStatement preparedStatement=null;
int rows = 0;
try {
// 准备语句对象
preparedStatement = connection.prepareStatement(sql);
// 设置语句上的参数
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i+1,args[i]);
}
// 执行 增删改 executeUpdate
rows = preparedStatement.executeUpdate();
// 释放资源(可选)
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != preparedStatement) {
try {
preparedStatement.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
JDBCUtil.releaseConnection();
}
// 返回的是影响数据库记录数
return rows;
}
}
TestBaseDao
package com.atguigu.schedule.test;
import com.atguigu.schedule.dao.BaseDao;
import com.atguigu.schedule.pojo.SysUser;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.List;
public class TestBaseDao {
private static BaseDao baseDao;
/*
* @BeforeClass 只执行一次,在当前测试类的所有测试方法执行之前,必须静态
* @BeforeMethod 在每个@Test方法执行之前都会执行,不必是静态的
*/
@BeforeClass
// @BeforeClass标注的方法必须是静态方法,且里面使用的变量也只能是静态成员变量
// @BeforeClass标注的方法将在当前测试类中的所有测试方法执行之前只执行一次
public static void initBaseDao(){
baseDao = new BaseDao();
}
@Test
public void testBaseQueryObject(){
// 查询用户数量 baseQueryObject 查询结果集是单行 单列的 一个值的数据的方法
// 使用baseDao对象调用baseQueryObject方法执行sql查询,返回的数据用Long封装
// 下面这条语句返回表格行数,count(1)和count(*)效果类似
String sql ="select count(1) from sys_user";
Long count = baseDao.baseQueryObject(Long.class, sql);
System.out.println(count);
}
/*
baseQuery 用于返回多个对象或对象集合,比如List<T>或Set<T>,用于查询多条记录。
baseQueryObject 用于返回单个对象或值,比如T或基本数据类型的包装类(如Integer、Long等)用于查询一条记录或一个值
*/
@Test
public void testBaseQuery(){
// 表格中的字段user_pwd起别名为userPwd,才能和下面的实体类SysUser匹配
// 返回的结果有 uid、username、userPwd,故用SysUser封装
String sql ="select uid,username,user_pwd userPwd from sys_user";
List<SysUser> sysUserList = baseDao.baseQuery(SysUser.class, sql);
sysUserList.forEach(System.out::println);
}
@Test
public void testBaseUpdate(){
// 增加一条记录:values中的DEFAULT表示递增到最后一行,三个?表示三个属性,在下面的括号中定义(1, "学习Java", 0)
// baseDao.baseUpdate 返回影响数据库记录的行数,rows = 1,说明增加了一条记录
String sql ="insert into sys_schedule values(DEFAULT,?,?,?)";
int rows = baseDao.baseUpdate(sql, 1, "学习Java", 0);
System.out.println(rows);
}
}