6

今天准备了一个使用Spring Boot的例子,在Spring-MyBatis旁边使用MyBatis进行数据访问通信。这是相关的项目配置(使用maven):

src/main/java
- edu.home.ltmj.controller
  + CategoryController.java
- edu.home.ltmj.dao
  + CategoryDao.java
- edu.home.ltmj.domain
  + Category.java
src/main/resources
- edu.home.ltmj.dao
  + CategoryMapper.xml

文件的相关内容:

CategoryDao.java:

package edu.home.ltmj.dao;

public interface CategoryDao {
    List<Category> getAllCategories();
}

类别映射器.xml:

<mapper namespace="edu.home.ltmj.dao.CategoryDao">
    <resultMap id="categoryMap"
        type="edu.home.ltmj.domain.Category">
        <id property="id" column="id" />
        <result property="name" column="name" />
    </resultMap>
    <select id="getAllCategories" resultMap="categoryMap">
        SELECT id, nombre
        FROM category
    </select>
</mapper>

然后,我在请求控制器中注入这个 dao 的一个实例(用于测试目的),如下所示:

package edu.home.ltmj.controller;

@RestController
public class CategoryController {
    @Autowired
    private CategoryDao dao;

    @RequestMapping(value="/category/all",
        method=RequestMethod.GET,
        produces=MediaType.APPLICATION_JSON_VALUE)
    public List<Categoria> getAllCategories() {
        return dao.getAllCategories();
    }
}

我运行我的项目并通过使用测试执行curl localhost:8080/category/all,然后期望看到 JSON 格式的结果,但我得到了这个异常:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): edu.home.ltmj.dao.CategoryDao.getAllCategories
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:189)
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:43)
at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:58)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:51)
at com.sun.proxy.$Proxy45.getAllCategories(Unknown Source)
at edu.home.ltmj.controller.CategoryRestController.getAllCategories(CategoryRestController.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
(...)

我不明白这是什么原因。有一个接口CategoryDao,它有与 .getAllCategories匹配的正确方法<select id="getAllCategories">。在玩了一段时间后,我将 dao 接口的名称更改为CategoryMapper并更新了 CategoryMapper.xml 中的命名空间。在我这样做之后,一切正常。此外,在类和 xml 具有相同名称后,我将 dao 类和 xml 映射器移动到不同的包中(仍然使用相同的名称:CategoryMapper。),更新 xml 文件中的命名空间,并得到相同的异常, 更新消息以显示 dao 接口的包名。但是话又说回来,我将两个文件都移到了同一个包中,一切都恢复了。

所以,我的问题是:为什么 MyBatis 需要接口和 xml 映射器文件具有相同的名称并在同一个包中?这是 MyBatis 的设计还是 Spring MyBatis 的问题?

4

2 回答 2

6

你也有一个 MyBatis 配置文件吗?

如果我没记错的话,当您想要一个无需额外配置即可工作的设置时,XML 文件的名称与界面相同。

如果您在其他地方有 XML 映射器,您可以使用MyBatis 配置<mappers>中的元素手动指定 XML 文件的类路径。

注入映射器文档:

如果 UserMapper 在与 mapper 接口相同的 classpath 位置有对应的 MyBatis XML mapper 文件,它会被 MapperFactoryBean 自动解析。除非映射器 XML 文件位于不同的类路径位置,否则无需在 MyBatis 配置文件中指定映射器。有关详细信息,请参阅 SqlSessionFactoryBean 的 configLocation 属性。

所以试试这个:

  1. 在其中创建一个mybatis-config.xml文件src/main/resources

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
      <mappers>
        <mapper resource="com/test/path/etc/etc/WhateverNameYouWant.xml"/>
      </mappers>
    </configuration>
    

    其中WhateverNameYouWant.xml包含您所CategoryMapper.xml包含的内容。

  2. 设置配置文件的位置(Java配置如下或applicationContext文件中的bean):

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        // ....
        sessionFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
        // ....
        return sessionFactory;
    }
    
于 2015-05-16T12:49:11.873 回答
1

我在没有@MapperScan 的情况下使用了以下方式,如下所示:

1) 设置 mybatis-config.xml 就像上面的步骤 2

@Bean
public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
    SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    // ....
    sessionFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
    // ....
    return sessionFactory;
}

2) 设置 CategoryDao

@Bean
public CategoryDao getCategoryDao() throws Exception{
    SqlSessionTemplate sessionTemplate = new SqlSessionTemplate(sqlSessionFactoryBean());
    return sessionTemplate.getMapper( CategoryDao.class );
}

3) 在 mybatis-config.xml 中设置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

    <settings>
        <setting name="logImpl" value="COMMONS_LOGGING"/>
    </settings>

    <mappers>

        <mapper class="CategoryMapper.xml"/>
    </mappers>

</configuration>
于 2015-05-17T01:45:11.297 回答