Mapper XML已经出现在target目录,调用仍报 Invalid bound statement,不能就此排除配置问题。文件被打包、资源被加载、statement被注册,是三个不同阶段。

这次最后发现的是前缀拼错

2019年整合Spring Boot和MyBatis时,调用DAO报:

Invalid bound statement (not found): com.dao.DeptDao.findAll

我检查过输出目录,XML确实存在;继续调试加载过程,发现映射内容没有读进去。最后逐项核对application.yml,才找到 mybatis 前缀拼写错误,下面的mapper-locations没有按预期绑定。改正后,当时的问题解决。

这是一种具体原因,不是该错误的唯一解释。

对照一个明确的最小映射关系

使用普通MyBatis Spring Boot Starter,假设接口叫 example.mapper.DeptMapper:

package example.mapper;

import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface DeptMapper {
    List<Map<String, Object>> findAll();
}

对应XML放到约定资源目录,namespace与接口全名、id与方法名一致:

<mapper namespace="example.mapper.DeptMapper">
  <select id="findAll" resultType="map">
    SELECT id, name FROM demo_department
  </select>
</mapper>

相关YAML示例:

mybatis:
  mapper-locations: classpath*:/mapper/**/*.xml

这里的表需要测试工程实际提供;示例只说明契约,不是即插即用数据库应用。使用MyBatis-Plus时要查对应的 mybatis-plus 配置体系;多个SqlSessionFactory或自定义配置时,也可能绕过默认加载逻辑。MyBatis Starter配置

按加载链条找,不只盯着target

依次检查当前profile与最终生效配置、资源匹配表达式、实际运行的JAR内容、XML解析错误、namespace/id和Mapper绑定的工厂。IDE输出目录存在某文件,不保证部署包中也有;Java接口已扫描,也不代表XML语句已注册。

若实际路径是 /mappers/ 而非 /mapper/,就按实际布局修改,不能机械照抄示例。

诊断日志按Mapper范围临时开启

另一条2018年笔记通过Mapper包名打开日志。properties形式:

logging.level.example.mapper=DEBUG

YAML形式:

logging:
  level:
    example.mapper: DEBUG

包名不固定,也不必把每个点拆成一层。还要确认MyBatis实际选择的日志实现与应用的输出配置一致。MyBatis日志说明

SQL及参数可能包含用户资料,只在必要范围和时间内诊断,避免长期记录敏感输入。日志是观察手段,不会替你注册缺失的statement。