10

Here is the stack trace when I try to execute a simple query using MyBatis:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.my.package.persistence.BrandMapper.getBrand
    org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:189)
    org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:43)
    org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:58)
    org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:51)
    com.sun.proxy.$Proxy25.getBrand(Unknown Source)
    com.my.package.service.BrandService.getBrand(BrandService.java:18)
    com.my.package.service.BrandService$$FastClassBySpringCGLIB$$1140c60a.invoke(<generated>)
    org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:649)
    com.my.package.service.BrandService$$EnhancerBySpringCGLIB$$ea6f89cd.getBrand(<generated>)
    com.my.package.controller.HomeController.getBrands(HomeController.java:28)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:483)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:706)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

I'm using Javaconfig syntax instead of XML configuration. Here is my PersistenceConfig:

@Configuration
@EnableTransactionManagement
@MapperScan("com.my.package.persistence")
public class PersistenceConfig {

    @Bean
    public DataSource dataSource() {

        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        try {
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql//localhost:3306/db");
            dataSource.setUsername("dbuser");
            dataSource.setPassword("dbpassword");
        } catch (Exception e) {
            System.out.print(e);
        }
        return dataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setTypeAliasesPackage("com.my.package.domain");
        return sessionFactory;
    }
}

Here is my controller:

@Controller
public class HomeController {

    private static Logger logger = LoggerFactory.getLogger(HomeController.class);

    @Autowired
    private BrandService brandService;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index() {
        return "index";
    }

    @RequestMapping(value = "/brands", method = RequestMethod.GET)
    public String getBrands(Model model) {
        model.addAttribute("brands",brandService.getBrand(1));
        return "brands";
    }

}

Here is my Brand Mapper Interface:

public interface BrandMapper {

    Brand getBrand(int id);

    Brand getBrandByName(String name);

    List<Brand> getBrandList();

    void addBrand(Brand brand);

    void updateBrand(Brand brand);

    void deleteBrand(int id);

}

Here is my BrandMapper 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.my.package.persistence.BrandMapper">

    <select id="getBrand" resultType="Brand" parameterType="int">
        SELECT id, name
        FROM brand
        WHERE id = #{id};
    </select>

    <select id="getBrandByName" resultType="Brand" parameterType="String">
        SELECT id, name
        FROM brand
        WHERE name = #{name};
    </select>

    <select id="getBrandList" resultType="Brand">
        SELECT id, name
        FROM brand;
    </select>

    <insert id="addBrand" parameterType="Brand">
        INSERT INTO brand (id, name)
        VALUE (#{id}, #{name})
    </insert>

    <update id="updateBrand" parameterType="Brand">
        UPDATE brand
        SET
        name = #{name}
        where id = #{id}
    </update>

    <delete id="deleteBrand" parameterType="int">
        DELETE FROM brand
        WHERE id = #{id}
    </delete>

</mapper>

I've done some research, but none of the solutions have worked for me. My XML Mapper files are under resources in a package named "com.my.package.persistence"

Does anyone have an idea what's wrong here?

Thanks in advance

Jail
  • 880
  • 2
  • 15
  • 29

10 Answers10

9

Try checking the mybatis-conf.xml (whatever name your called this file) file and see if you have your xml mapper like this:


<mappers> 
    <mapper resource="BrandMapper.xml">
<mappers>
5

Error message:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):

Most probably due to a wrong mapper Query Syntax. I had this problem many times and every time the error is caused by a wrong syntax of the query written in the Mapper xml and interface files. I suggest you to,

  • Re-check your query properly which is mainly the reason for this error.
  • Configuration => Might also be caused due to invalid configuration of mapper files(interface & xml) in configuration files.
  • Do maven clean, maven install(rebuild) and then restart the server
Lucky
  • 16,787
  • 19
  • 117
  • 151
3

You should provide mapper locations when initialize sqlSessionFactory:

    @Autowired
    private ResourceLoader resourceLoader;

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        //sessionFactory.setTypeAliasesPackage("com.my.package.domain");
        sessionFactory.setMapperLocations(ResourcePatternUtils.getResourcePatternResolver(resourceLoader).
            getResources("classpath:path/to/mappers/*.xml"));
        return sessionFactory;
   }

In your case, replace "classpath:path/to/mappers/*.xml" with classpath:com/my/package/persistence/*.xml

Hope this will help you.

1

If you had run the JUNIT of the db service code, it would have worked. Hence I believe its the probmlem when WAR file is generated, from your configuration *Mapper.java and *Mapper.xml points to same location, Hence when war is gerenated folder path for both java and xml files would be WEB-INF/classes/com/my/package/persistence. However *.xml file is not copied to the location. One way is to configure you build script to copy the xml files as well or otherway(which I would prefer) to create sqlmap directory in resources directory and copy all the xml mapper files to the directory and point to mapperfile location using sessionFactory.setMapperLocations and once war file is generated make sure sqlmap directory is present in WEB-INF/classes directory

Karthik Prasad
  • 9,662
  • 10
  • 64
  • 112
1

I had this exact error message, turned out to be the namespace path in the mapper xml file, I had changed the package name in the java interface file but forgot to update the package name in the maper xml, bit of an odd one. Updated the package namespace and hey presto!

derek
  • 476
  • 5
  • 11
1

In resource, make a dir is "com/stackflow/mapper", not is "com.stackflow.mapper". because The former is a filename, the latter is dirs

Codemaker2015
  • 12,190
  • 6
  • 97
  • 81
炎权梁
  • 11
  • 1
0

I guess Maybe you need a @Alias annotation:

@Alias("Brand") class Brand{ ... }

this is the first thing comes to my mind hope it helps !

S_intg
  • 182
  • 1
  • 10
0

Remove the ; from the query:

<select id="getBrand" resultType="Brand" parameterType="int">
    SELECT id, name
    FROM brand
    WHERE id = #{id}
</select>
Akash Rajbanshi
  • 1,553
  • 11
  • 23
0

Your mapper file should be in the same package as the *Repo.java file is. Please check the mapper namespace too.

Sravan
  • 1
  • 1
  • 3
0

Just fixed with gradle clean build.

user3399000
  • 353
  • 3
  • 18