mybatis spring mvc application, getting Invalid bound statement (not found)

Learn mybatis spring mvc application, getting invalid bound statement (not found) with practical examples, diagrams, and best practices. Covers spring, spring-mvc, mybatis development techniques wi...

Resolving 'Invalid bound statement (not found)' in Spring MVC with MyBatis

Hero image for mybatis spring mvc application, getting Invalid bound statement (not found)

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.

@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.