关于MyBatis在IDEA中进行工具类封装的空指针异常
请赐给我一双火眼金睛
看视频学编程最大的痛苦莫过于——跟着视频一步一步走,他运行成功了,而你出了一堆Bug…
操作mybatis对象
回忆一下创建一个简单的mybatis工程进行数据库增删改查操作的基本步骤:
- 新建数据库和数据表
- 加入maven的mybatis坐标、mysql驱动坐标
- 创建实体类,保存表中的一行数据(定义每一列的属性、set和get方法)
- 创建持久层的DAO接口,定义操作数据库的方法
- 创建一个mybatis使用的配置文件
sql映射文件:写SQL语句的,一个表一个映射文件,xml格式
xml文件位于接口所在的目录中,名称和接口保持一致 - 创建mybatis的著配置文件:
一个项目中一个主配置文件,提供了数据库链接信息和sql映射文件的位置信息 - 创建使用mybatis的对象
在进行完前六步操作后,就要创建一个使用者来调用这些类操作数据库了,一个基本的使用mybatis的对象创建步骤如下:
public class MyApp {
public static void main(String[] args) throws IOException {
//1、定义mybatis主配置文件的名称,从类路径根目录开始
String config = "mybatis-config.xml";
//2、读取config表示的文件
InputStream in = Resources.getResourceAsStream(config);
//3、创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//4、创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
//5、从SqlSessionFactory中获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//6、指定要执行的SQL语句的标识,sql映射文件中的namespace + "."+标签的id
String sqlid = "com.xduSF.dao.StudentDao.selectStudent";
//7、通过sqlid执行sql语句
List<Student> studentList = sqlSession.selectList(sqlid);
//8、输出结果
for (Student stu:studentList){
System.out.println("查询的学生 = "+stu);
}
//9、关闭SqlSession对象
sqlSession.close();
}
}
显然,前5步是可以重复使用的,因此将其封装到一个工具类MyBatisUtils中,于是我们新建了一个工具类如下:
public class MybatisUtils {
public static SqlSessionFactory factory = null;
static {
String config = "mybatis-config.xml"; //需要和项目中的文件名一致
try {
InputStream in = Resources.getResourceAsStream(config);
//创建SqlSessionFactory对象
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession的方法
public static SqlSession getSqlSession(){
SqlSession sqlSession = null;
if(factory!=null){
factory.openSession(); //非自动提交
}
return sqlSession;
}
}
这样在操作mybatis对象时可以通过调用其工具类,减少代码量:
SqlSession sqlSession = MybatisUtils.getSqlSession();
出Bug了。
运行测试程序从数据库中查找数据项,结果报空指针异常;
debug发现MybatisUtils.getSqlSession()处获取到的SqlSession对象始终为null,检查配置文件、实体类定义均未出错,数据库连接完好。
经过一系列排查,发现工具类写错了(给自己一个大耳刮子)
在获取SqlSession的方法中,首先初始化SqlSession对象为null,然后我没有定义SqlSession对象接收factory.openSession()的值,所以运行时该对象一直为空。
故正确的封装应为:
//...
//获取SqlSession的方法
public static SqlSession getSqlSession(){
SqlSession sqlSession = null;
if(factory!=null){
sqlSession = factory.openSession(); //非自动提交
}
return sqlSession;
}
//...
所以平时一定要细心,一定要保护好眼睛,要不bug放你眼前了都看不见。。。
自省ing…