springboot+mybatis,原生dao开发问题

最近想尝试一种比较简单的开发方法。
只在xml文件中写sql语句,传入和传出参数都是map。在controller和service中再做其他操作。

然后写了份测试代码。

这是通用Dao,service层传入sqlId和map类型的param,根据sqlId调用对应sql语句,返回结果也是map

public class BaseDao {

    private static SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();

    public static List<Map> select(String sqlId, Map param) {
        try {
            factoryBean.setDataSource(new DruidDataSource());
            SqlSessionFactory sessionFactory = factoryBean.getObject();
            SqlSession sqlSession = sessionFactory.openSession();
            return sqlSession.selectList(sqlId, param);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

自定义的mapper.xml

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.JinBoot">

    <select id="test" parameterType="hashMap" resultType="hashMap">
        select * from user
    </select>
</mapper>

在application中也做了配置

mybatis.mapperLocations=classpath:mapper/*.xml

执行的时候,经过controller接口和service层,传到Dao层的sqlId是mapper.JinBoot.test, param是空。
执行报错。

报错信息如下:

Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for mapper.JinBoot.test
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
    at cn.tianyustudio.jinboot.dao.BaseDao.select(BaseDao.java:20)
    at cn.tianyustudio.jinboot.service.BaseService.select(BaseService.java:10)
    at cn.tianyustudio.jinboot.controller.BaseController.test(BaseController.java:21)

上网查了下,大概意思是没有扫描到mapper.JinBoot.test这个id对应的sql语句,但mybatis中不是根据namespace+id来寻找的吗?我这里没有用mybatis的mapper映射方式(有对应的Dao.java),但通过这种手工指定id的方式理论上来说应该是可行的,是哪里的配置问题还是?

阅读 4.2k
3 个回答

把mapper里查询方法的id改成select.也就是dao的方法名.

mapper.JinBoot应该是一个接口,里面声明一个test方法,mapper.JinBoot贴出来看看
报错源码

public V get(Object key) {
/* 670 */       V value = super.get(key);
/* 671 */       if (value == null) {
/* 672 */         throw new IllegalArgumentException(this.name + " does not contain value for " + key);
/*     */       }
/* 674 */       if ((value instanceof Ambiguity)) {
/* 675 */         throw new IllegalArgumentException(((Ambiguity)value).getSubject() + " is ambiguous in " + this.name + " (try using the full name including the namespace, or rename one of the entries)");
/*     */       }
/*     */       
/* 678 */       return value;
/*     */     }
protected final Map<String, MappedStatement> mappedStatements = new StrictMap("Mapped Statements collection");

Mybatis会解析xml文件,使用StrictMap把namespace+id作为key,MappedStatement作为value存储起来,执行selectList方法时会根据sqlId查找对应的MappedStatement,如果value为null,则报出这个异常 Mapped Statements collection does not contain value for mapper.JinBoot.test。

是不是被加进了IncompleteStatement这个集合? XML文件读取转换失败的话会直接加进这个集合,不会报异常的。

建议打断点看看,mapper文件的扫描都会经过这个方法

// 出处
// mybatis-3.4.4.jar
// org.apache.ibatis.builder.xml.XMLMapperBuilder line:132
private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
    for (XNode context : list) {
      final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
      try {
        statementParser.parseStatementNode();
      } catch (IncompleteElementException e) {
        configuration.addIncompleteStatement(statementParser);
      }
    }
  }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题