sqlsessionfactory 初始化不报 nullpointerexception的关键是确保配置文件路径正确、xml格式合法且被classpath加载:mybatis-config.xml须置于src/main/resources下,根节点为并包含和,mapper xml的namespace需与接口全限定名严格一致,且sqlsessionfactory应作为线程安全的全局单例使用。

SqlSessionFactory 怎么初始化才不会报 NullPointerException
MyBatis 启动失败十次里有八次卡在这步——SqlSessionFactory 没建出来,后面所有 sqlSession.openSession() 全挂。核心就一条:配置文件路径错、XML 格式错、资源没加载进 classpath,它就直接返回 null,不抛异常,只默默给你一个空指针。
-
SqlSessionFactoryBuilder().build()的输入流必须来自Resources.getResourceAsStream("mybatis-config.xml"),别手写new FileInputStream("src/main/resources/..."),IDE 打包后路径根本不存在 - 确保
mybatis-config.xml在src/main/resources下,且文件名拼写完全一致(区分大小写),Maven 构建时默认只打包该目录下的非.java文件 - XML 根节点必须是
<configuration></configuration>,里面至少得有<environments></environments>和<mappers></mappers>,缺一不可;<mapper resource="xxx.xml"></mapper>的路径是相对于 classpath 的,比如 mapper 文件在mapper/UserMapper.xml,这里就得写"mapper/UserMapper.xml"
mybatis-config.xml 里 <environments></environments> 配置错在哪
常见现象是连上数据库了但查不出数据,或者抛 org.apache.ibatis.exceptions.PersistenceException,根源常在事务管理器和数据源配置不匹配。
- 如果用原生
UNPOOLED或POOLED,<transactionmanager type="JDBC"></transactionmanager>是唯一安全选项;选"MANAGED"就等于把事务甩给容器(如 Spring),单独跑 MyBatis 会静默失效 -
<datasource type="POOLED"></datasource>要求必须配全driver、url、username、password四个属性,漏一个就会在build()阶段抛IllegalArgumentException,错误信息里带"Property 'xxx' not specified" - MySQL 8+ 必须用
com.mysql.cj.jdbc.Driver,URL 末尾加?serverTimezone=UTC&useSSL=false,否则可能连通但查出的java.time.LocalDateTime字段全是 null
Mapper XML 文件加载失败的三个典型信号
运行时不报错,但调用 sqlSession.getMapper(UserMapper.class) 返回 null,或执行方法时抛 BindingException: Invalid bound statement——基本就是 mapper 没被识别。
- 检查
<mappers></mappers>里是不是用了<mapper class="xxx.UserMapper"></mapper>却忘了接口对应 XML 文件名必须是UserMapper.xml,且放在同一包路径下(或按 classpath 规则对齐) - 用
<mapper resource="..."></mapper>时,路径不能含file:或绝对路径,只能是 classpath-relative,例如"com/example/mapper/UserMapper.xml",对应 src/main/resources/com/example/mapper/ - XML 文件里的
<mapper namespace="com.example.mapper.UserMapper"></mapper>必须和接口全限定名严格一致,少个点、大小写错、包名不同,都会导致绑定失败
为什么 SqlSessionFactory 必须单例且线程安全
每次 new 一个 SqlSessionFactoryBuilder().build() 看似能跑,但实际会重复解析 XML、重建映射关系、浪费连接池资源,性能掉一半不止;更麻烦的是,多个实例之间缓存不共享,二级缓存形同虚设。
立即学习“Java免费学习笔记(深入)”;
- 官方明确说明
SqlSessionFactory是线程安全的,应该作为全局单例存在,Spring 里通常交给@Bean管理,纯 Java 应用建议用静态内部类或枚举实现懒汉式单例 - 不要在 service 方法里临时 build,也不要按请求 new,哪怕只测一次也埋下并发隐患;它的构建开销大,但使用成本极低
- 如果你看到项目里有
static SqlSessionFactory factory = null;+ 同步块初始化,其实不如直接用static final SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(...);——只要配置文件确定,它就是不可变的
真正容易被忽略的是:XML 解析失败时,MyBatis 默认吞掉部分异常堆栈,只留最外层提示。遇到 SqlSessionFactory 为 null,第一反应不该是改代码逻辑,而是立刻检查 classpath 下有没有那个 config 文件、内容是否合法、字符编码是不是 UTF-8(尤其 Windows 记事本保存的 XML 常带 BOM 头,导致解析器直接跪)










