今天我正在准备一个使用Spring Boot并使用MyBatis进行Spring-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();
}
CategoryMapper.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中的命名空间。在我这样做之后,一切正常。此外,在为class和xml命名之后,我将dao类和xml映射器移动到不同的包中(stil使用相同的名称同时为:CategoryMapper。),更新了xml文件中的命名空间,并获得了相同的异常,更新消息以显示dao接口的包的名称。但话说回来,我把两个文件都移到同一个包中,一切都恢复了。
所以,我的问题是:为什么MyBatis需要接口和xml映射器文件具有相同的名称并且在同一个包中?这是MyBatis设计还是Spring MyBatis中的一个问题?
答案 0 :(得分:6)
您是否还有MyBatis配置文件?
如果我没有正确记住XML文件的相同名称与界面相同,那么当您希望设置无需额外配置时即可使用。
如果您在其他地方有XML映射器,则可以使用MyBatis configuration内的<mappers>
元素手动指定XML文件的类路径。
来自Injecting Mappers documentation:
如果UserMapper在与mapper接口相同的类路径位置中具有相应的MyBatis XML映射器文件,则它将由MapperFactoryBean自动解析。除非映射器XML文件位于不同的类路径位置,否则无需在MyBatis配置文件中指定映射器。有关更多信息,请参阅SqlSessionFactoryBean的configLocation属性。
所以试试这个:
在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
包含的内容。
设置配置文件的位置(如下所示的Java配置或applicationContext
文件中的bean):
@Bean
public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
// ....
sessionFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
// ....
return sessionFactory;
}
答案 1 :(得分:1)
我在没有@MapperScan的情况下使用了以下方法,如下所示:
1)按照上面的第2步设置mybatis-config.xml
@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>