mybatis spring mvc application, getting Invalid bound statement (not found)
Categories:
Resolving 'Invalid bound statement (not found)' in Spring MVC with MyBatis

A comprehensive guide to diagnosing and fixing the common 'Invalid bound statement (not found)' error when integrating MyBatis with Spring MVC applications.
The 'Invalid bound statement (not found)' error is one of the most frequently encountered issues when setting up or debugging a Spring MVC application that uses MyBatis for data persistence. This error indicates that MyBatis cannot find the SQL statement corresponding to the method being called in your Mapper interface. It's a clear sign that there's a mismatch or misconfiguration between your Java Mapper interface and its XML mapping file. This article will walk you through the common causes and provide systematic solutions to resolve this frustrating error.
Understanding the MyBatis Binding Process
Before diving into solutions, it's crucial to understand how MyBatis binds your Java Mapper interfaces to SQL statements. MyBatis uses a proxy pattern: when you inject a Mapper interface into your Spring service, MyBatis creates an implementation on the fly. This implementation then looks for a corresponding SQL statement in an XML mapping file (or via annotations) based on the fully qualified name of the Mapper interface and the method name. If it can't find a match, the 'Invalid bound statement' error occurs.
flowchart TD A[Spring Service] --> B["Mapper Interface (e.g., `UserMapper`)"] B --> C["MyBatis Proxy (Runtime)"] C --> D["Locate SQL Statement (XML/Annotations)"] D -- "Match Found" --> E[Execute SQL] D -- "No Match Found" --> F["Error: Invalid bound statement (not found)"]
MyBatis Mapper Binding Process
Common Causes and Solutions
The 'Invalid bound statement (not found)' error typically stems from a few key areas. Systematically checking these points will usually lead to a resolution.
1. Mismatched Namespaces and IDs
The most frequent cause is a mismatch between the Mapper interface's fully qualified name and the namespace declared in the XML mapping file, or a mismatch between the method name in the interface and the id
of the SQL statement in the XML file.
package com.example.mapper;
public interface UserMapper {
User findById(Long id);
}
<?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="findById" resultType="com.example.model.User">
SELECT id, name, email FROM users WHERE id = #{id}
</select>
</mapper>
Ensure that the namespace
attribute in your XML mapping file exactly matches the fully qualified name of your Mapper interface (including package). Also, the id
of the <select>
, <insert>
, <update>
, or <delete>
tag must exactly match the method name in the interface.
2. Incorrect Mapper Location or Configuration
Spring needs to know where to find your MyBatis Mapper interfaces and XML mapping files. If the configuration is incorrect, Spring won't be able to scan and register them properly.
@Configuration
@MapperScan("com.example.mapper")
public class MyBatisConfig {
// ... DataSource and SqlSessionFactoryBean configuration
}
Verify that the @MapperScan
annotation in your Spring configuration points to the correct base package where your Mapper interfaces reside. If you're using XML-based Spring configuration, check the <mybatis:scan base-package="com.example.mapper"/>
tag.
src/main/resources
), you need to explicitly configure the mapperLocations
property in your SqlSessionFactoryBean
.@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/**/*.xml"));
return factoryBean.getObject();
}
The classpath*:mapper/**/*.xml
pattern tells Spring to look for XML files in any mapper
directory within the classpath, and in any subdirectories. Adjust this path to match your project structure.
3. XML Mapping Files Not Included in Build
A common oversight is that the XML mapping files are not being copied to the target classes
directory during the build process. This often happens when they are placed in src/main/java
alongside the .java
files, but the build system (Maven/Gradle) is not configured to include non-Java resources from that directory.
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
Add the above <resources>
block to your pom.xml
(if using Maven) to ensure that XML files located in src/main/java
(alongside your interfaces) and src/main/resources
are included in the final .jar
or .war
artifact. For Gradle, you'd configure a similar resource inclusion in your build.gradle
file.
4. Caching Issues or IDE Problems
Sometimes, after making changes, the build system or IDE might not pick them up immediately. This can lead to stale configurations or missing resources.
1. Clean and Rebuild Project
Perform a clean build of your project. In Maven, this is mvn clean install
. In Gradle, gradle clean build
. This ensures all old build artifacts are removed and new ones are generated.
2. Invalidate Caches and Restart IDE
If using an IDE like IntelliJ IDEA or Eclipse, try invalidating caches and restarting the IDE. This can resolve issues where the IDE's internal state is out of sync with the project files.
3. Verify Deployed Artifact
Manually inspect the deployed .jar
or .war
file. Unzip it and check if your Mapper XML files are present in the correct package structure within the classes
directory.