MyBatis 教程

MyBatis 笔记

解决 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 的问题

MyBatis 笔记 MyBatis 笔记


在 mybatis 开发中,如果遇到 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 的异常信息,表示我们的 mybatis dao 相关接口与 mapper 的配置文件之间的映射绑定关系出现了问题,常见的问题原因有如下几种。

配置问题

mapper location 没有配置

以 spring boot yml 配置为例,未在 application.yml 上进行如下配置:

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

以 spring boot 基于 java 配置为例,如下:

package demo.config;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;


@Configuration
@MapperScan(basePackages = {"demo.mapperWrong"}, sqlSessionTemplateRef = "testSqlSessionTemplate")
public class DBConfig {

    @Bean(name = "testDataSource")
    @ConfigurationProperties("datasource.test")
    public DataSource dataSource() {
        HikariDataSource hikariDataSource = (HikariDataSource) DataSourceBuilder.create().build();
        return hikariDataSource;
    }

    @Bean(name = "testSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("testDataSource") DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        try {
            //  没有如下配置,且 @MapperScan 的 basePackages 未为 xml 和 mapper(dao)所在路径时
//            sqlSessionFactoryBean.setMapperLocations(resourcePatternResolver.getResources("classpath*:demo/mapper/*.xml"));
            return sqlSessionFactoryBean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Bean(name = "testDataSourceTransactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("testDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "testSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("testSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

mapper scan 配置问题

mapper(或者 dao)和 mybatis 对应 bean 的 xml 配置路径不对。

最典型的是,配置路径名称中包含的点作为包名称的一部分,而不是包路径的分割符,如下:

DemoMapper 放在了 package demo.mapper 路径下,而对应的 xml 文件放在了 resources 下面的 demo.mapper 名下(IDE 的操作不当,这时要细看当前 demo.mapper 是路径名称还是类似包路径的 demo/mapper),如果此时的 mapper location 配置是 classpath*:demo/mapper/*.xml 就会报未绑定的错误;解决方法是修改 xml 配置的路径(注意 IDE 操作),或者直接可以把配置改成 classpath*:demo.mapper/*.xml

名称问题

bean xml 文件的 sql 相关的方法名不匹配

bean xml 中的 sql 相关方法名不匹配,如下:

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="demo.mapper.DemoMapper">
    <resultMap id="baseResultMap" type="demo.entity.Test">
        <id column="id" property="id"/>
        <result column="rich_text_html" property="richTextHtml"/>
    </resultMap>
    <sql id="baseColumnList">
      id, rich_text_html
    </sql>
    <sql id="tableName">
        knowledge
    </sql>
    <select id="selLis" resultMap="baseResultMap">
        select
        <include refid="baseColumnList"/>
        from
        <include refid="tableName"/>
        <where>
            1 = 1
        </where>
    </select>
</mapper>
package demo.mapper;

import demo.entity.Test;
import java.util.List;

public interface DemoMapper {

    List<Test> selList();

}

mapper(或者 dao)里的 selList 方法名和 xml 配置的 selLis 不匹配,针对此问题除了错误发生时,异常报出之外,还可以通过 IDE 中 mybatis 相关插件可以在编码阶段得到错误的提示。