myBatis中的莫名其妙的java.lang.NullPointerException,求指教

在使用MyBatis时,出现java.lang.NullPointerException可能由多种原因引起。要解决这个问题,可以从以下几个方面进行排查和调试:

常见原因及解决方法

  1. Mapper接口未正确注入

    • 确保Mapper接口正确地被Spring或者MyBatis注入。如果使用Spring,请检查是否正确配置了Mapper扫描。
    • 配置示例:
      xml
      <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath*:mappers/*.xml"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.example.mapper"/> </bean>
      或者使用注解:
      java
      @MapperScan("com.example.mapper") @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
  2. SQL映射文件未正确加载

    • 确保Mapper XML文件路径配置正确,并且与Mapper接口的方法对应。
    • 示例:
      xml
      <mapper namespace="com.example.mapper.UserMapper"> <select id="findUserById" parameterType="int" resultType="com.example.model.User"> SELECT * FROM users WHERE id = #{id} </select> </mapper>
  3. Result Map未正确配置

    • 如果使用了ResultMap,确保配置正确,并且字段名与数据库中的列名对应。
    • 示例:
      xml
      <resultMap id="userResultMap" type="com.example.model.User"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="email" column="email"/> </resultMap> <select id="findUserById" resultMap="userResultMap"> SELECT * FROM users WHERE id = #{id} </select>
  4. Mapper接口方法返回值

    • 确保Mapper接口的方法返回值类型正确。
    • 示例:
      java
      public interface UserMapper { User findUserById(int id); }
  5. 传递给Mapper方法的参数

    • 确保传递给Mapper方法的参数不为null,且参数类型正确。
    • 示例:
      java
      int userId = 1; // 确保userId不为null User user = userMapper.findUserById(userId);

调试步骤

  1. 检查Mapper接口和实现

    • 确保Mapper接口被正确扫描并注入到Spring上下文中。可以通过日志或者调试检查Mapper接口是否为null。
    • 示例:
      java
      @Autowired private UserMapper userMapper; public void someMethod() { if (userMapper == null) { System.out.println("UserMapper is null"); } }
  2. 检查SQL映射文件路径

    • 确保SQL映射文件的路径正确,并且被加载。可以通过日志或者调试检查SQL映射文件是否被正确加载。
    • 示例:
      java
      SqlSessionFactory sqlSessionFactory = ... Configuration configuration = sqlSessionFactory.getConfiguration(); Collection<String> mappedStatements = configuration.getMappedStatementNames(); mappedStatements.forEach(System.out::println); // 输出所有被加载的SQL映射
  3. 启用MyBatis日志

    • 启用MyBatis的日志输出,检查SQL执行情况,是否有SQL执行失败或者结果为空的情况。
    • 配置示例:
      xml
      <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>

示例代码

以下是一个完整的示例,包括Spring Boot应用中的MyBatis配置、Mapper接口、SQL映射文件和测试代码。

Spring Boot配置

java
@SpringBootApplication @MapperScan("com.example.mapper") public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }

数据源配置(application.properties)

properties
spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=root spring.datasource.password=password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver mybatis.mapper-locations=classpath*:mappers/*.xml

Mapper接口

java
package com.example.mapper; import com.example.model.User; import org.apache.ibatis.annotations.Select; public interface UserMapper { @Select("SELECT * FROM users WHERE id = #{id}") User findUserById(int id); }

SQL映射文件(resources/mappers/UserMapper.xml)

xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mapper.UserMapper"> <select id="findUserById" resultType="com.example.model.User"> SELECT * FROM users WHERE id = #{id} </select> </mapper>

测试代码

java
package com.example; import com.example.mapper.UserMapper; import com.example.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class MyRunner implements CommandLineRunner { @Autowired private UserMapper userMapper; @Override public void run(String... args) throws Exception { User user = userMapper.findUserById(1); if (user != null) { System.out.println(user.getName()); } else { System.out.println("User not found"); } } }

通过以上步骤,可以有效地排查和解决MyBatis中出现的java.lang.NullPointerException问题。