mybatis 第一个demo,并记一次解决问题:Mapped Statements collection does not contain value for

这个问题是我这边博文的最关键的地方,因为这个问题,浪费了几个小时的时间,搜索了天知道多少篇说这个问题的文章,他们提到的解决方案,包括以下:

1.没有注册,就是没有添加下面的mappers的内容

2.namespace 那里要写对,注册的内容和命名空间的值要一致

 

 

 

整个博文的总结:  对一个mapper的xml文件,要是想引用一个方法,有两个途径:

 

一、参数直接传那个方法的名字,即定义的id值,上图中1的部分(当然,可能前提是添加了上文提到的build部分的代码才可以!)

二、参数传 namespace+id的值,即上图中1和2的拼接,结果为mapper.UserMapper.xml.getUser

测试结果,上文已经有了!

 

 

 

 

 

 

 

 

 

 

—————————————————————————————————————————————————————

 

第一部分:第一个项目

环境:

os:windows 7

ide:idea 2019.1.1 

jre:1.8.0

 

一路OK下去。

然后右键点击项目,

设置maven管理

 

添加依赖,并同步:

 <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.8</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

准备工作到此完成,现在开始搞代码逻辑。

项目结构如下所示:

 

分别代码如下所示:

package bean;

public class User {

    private int id;
    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public User() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

package controller;

import bean.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class main {

    public static void main(String[] args) {
        String resource = "mybatis-config.xml";
        InputStream inputStream;

        try {
            inputStream = Resources.getResourceAsStream(resource);

            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            SqlSession session = sqlSessionFactory.openSession();
            User user = session.selectOne("mapper.UserMapper.getUser",1);
            System.out.println("用户id:"+user.getId()+"\t用户名称:"+user.getName());


        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

 

UserMapper.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="mapper.UserMapper.xml">

    <select id="getUser" parameterType="int" resultType="bean.User">
    select * from users where id = #{id}
    </select>


</mapper>

 

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>
    <properties resource="database.properties"/>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

 

database.properties:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db_name
username=xxxxx
password=xxxxx

  

 

--------------------------------------------------------------------------------------------------------

经过上面的步骤,似乎一切都OK了,知道你一跑起来,发现:

D:\java\bin\java.exe "-javaagent:D:\IDE\IntelliJ IDEA 2019.1.1\lib\idea_rt.jar=53832:D:\IDE\IntelliJ IDEA 2019.1.1\bin" -Dfile.encoding=UTF-8 -classpath D:\java\lib\ant-javafx.jar;D:\java\lib\deploy.jar;D:\java\lib\java.jnlp.jar;D:\java\lib\javafx-swt.jar;D:\java\lib\javaws.jar;D:\java\lib\jdk.deploy.jar;D:\java\lib\jdk.javaws.jar;D:\java\lib\jdk.plugin.dom.jar;D:\java\lib\jdk.plugin.jar;D:\java\lib\jrt-fs.jar;D:\java\lib\plugin-legacy.jar;D:\java\lib\plugin.jar;D:\workspace\server\mybatisDemo\target\classes;D:\workspace\server\mybatisDemo\lib\spring-aspects-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-aop-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-beans-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-context-support-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-context-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-core-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-instrument-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-instrument-tomcat-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-expression-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-jms-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-messaging-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-jdbc-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-orm-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-oxm-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-test-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-tx-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\commons-logging-1.2.jar;D:\workspace\server\mybatisDemo\lib\aopalliance-1.0.jar;C:\Users\Andrew\.m2\repository\mysql\mysql-connector-java\5.1.8\mysql-connector-java-5.1.8.jar;C:\Users\Andrew\.m2\repository\org\mybatis\mybatis\3.5.1\mybatis-3.5.1.jar controller.main
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: 
### Error building SqlSession.
### The error may exist in mapper/UserMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource mapper/UserMapper.xml
	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
	at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:64)
	at controller.main.main(main.java:21)
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource mapper/UserMapper.xml
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:121)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:98)
	at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:78)
	... 2 more
Caused by: java.io.IOException: Could not find resource mapper/UserMapper.xml
	at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:114)
	at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:100)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:371)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:119)
	... 4 more

Process finished with exit code 1

  

这种坑爹的问题,显然我们配置了对应的mapper/UserMapper.xml,仍旧找不到,只有一个问题,就是配置有问题,愚蠢的程序并不知道那个文件在哪里,需要被包括进来。

解决办法就是:在pom.xml文件中添加如下代码:

 <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>mybatis-config.xml</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>/src/main/resources</directory>
            </resource>
        </resources>
    </build>

  相信稍微有点悟性的少年已经明白为什么要这么做:为了让程序在整理打包的时候,把配置的xml文件包括进去

于是,整个的pom.xml就成了如下的样子:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>mybatis-config.xml</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>/src/main/resources</directory>
            </resource>
        </resources>
    </build>




    <groupId>mybatisId</groupId>
    <artifactId>mybatisDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.8</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

  

-------------------------------------------------------------------------------------------------

等你做完上面这些步骤之后,兴冲冲的一跑,仍旧会头痛啊头痛,难受啊难受~~~~~!

D:\java\bin\java.exe "-javaagent:D:\IDE\IntelliJ IDEA 2019.1.1\lib\idea_rt.jar=53890:D:\IDE\IntelliJ IDEA 2019.1.1\bin" -Dfile.encoding=UTF-8 -classpath D:\java\lib\ant-javafx.jar;D:\java\lib\deploy.jar;D:\java\lib\java.jnlp.jar;D:\java\lib\javafx-swt.jar;D:\java\lib\javaws.jar;D:\java\lib\jdk.deploy.jar;D:\java\lib\jdk.javaws.jar;D:\java\lib\jdk.plugin.dom.jar;D:\java\lib\jdk.plugin.jar;D:\java\lib\jrt-fs.jar;D:\java\lib\plugin-legacy.jar;D:\java\lib\plugin.jar;D:\workspace\server\mybatisDemo\target\classes;D:\workspace\server\mybatisDemo\lib\spring-aspects-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-aop-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-beans-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-context-support-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-context-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-core-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-instrument-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-instrument-tomcat-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-expression-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-jms-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-messaging-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-jdbc-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-orm-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-oxm-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-test-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\spring-tx-4.3.18.RELEASE.jar;D:\workspace\server\mybatisDemo\lib\commons-logging-1.2.jar;D:\workspace\server\mybatisDemo\lib\aopalliance-1.0.jar;C:\Users\Andrew\.m2\repository\mysql\mysql-connector-java\5.1.8\mysql-connector-java-5.1.8.jar;C:\Users\Andrew\.m2\repository\org\mybatis\mybatis\3.5.1\mybatis-3.5.1.jar controller.main
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for mapper.UserMapper.getUser
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for mapper.UserMapper.getUser
	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:149)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)
	at controller.main.main(main.java:23)
Caused by: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for mapper.UserMapper.getUser
	at org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:946)
	at org.apache.ibatis.session.Configuration.getMappedStatement(Configuration.java:739)
	at org.apache.ibatis.session.Configuration.getMappedStatement(Configuration.java:732)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:146)
	... 3 more

Process finished with exit code 1

  

这个问题是我这边博文的最关键的地方,因为这个问题,浪费了几个小时的时间,搜索了天知道多少篇说这个问题的文章,他们提到的解决方案,包括以下:

1.没有注册,就是没有添加下面的mappers的内容

2.namespace 那里要写对,注册的内容和命名空间的值要一致

···

还有不少,倒是记不清楚了,但是显然我这个工程是没有他们说的这个问题的。

在这个过程中,我近乎绝望地搜索了近3个小时,最后迫不得已,都特么靠不住,只有靠自己了!

接下来是解决问题的过程,与大家分享:

第一步:点击所有出错的语句,进行出错追踪,找到个坑爹的玩意儿到底哪里出了问题。

(其实不用想,肯定是找不到调用的方法,但是为什么找不到,这个才是需要解决的问题!)

 

然后就会出现对应的代码逻辑:

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)对应的代码:

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)对应的代码:

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:149) 对应的代码:

到了这里,就已经开始抛异常了,说明是第二幅图那里的代码出了问题!

 

然后第二幅图那里的代码又直接调用了另一个同名不同参的方法,如下图:

 

如果有人想重现这个步骤,那么像我一样在那一行的代码左边打上debug小红点,一步一步跑起来就行,接下来是逐步分析的过程,debug的进入是小红点这里。

 

 

第二步 debug操作

下面正式开始:

跑到第一个出错点  (如果图太大,看不清楚,可以右键在新窗口中打开,方法可以看清晰的图像)

 

显然并没有什么问题,于是点击上图红圈圈里,往下一个断点运行,下一个断点如下图所示

似乎也没有啥问题,因为毫无变化,除了传进来的两个参数,没有其余变化,继续,然而马上跑到抛异常的这里了显然是在这个过程中,出现的问题。

 

于是我们需要在没抛异常和抛异常之间的代码,翻得更精确一些,最好一步一步都打上断点,这样才能看到具体的出错过程,下面需要补充一些断点

 

通过观察出错的代码,上面的横线那里还没出错,因为上面的方法跳转到了下面那个方法里面,在下面方法里面出错了,出错的逻辑,必然在圈圈1,和圈圈2那两行代码里面,不然不可能这样跑出异常,于是把那两个方法都打上断点标记一下。

观察一下那个方法名字和代码逻辑,显然是搞了个字符串用来从配置xml文件里面找到对应的sql语句配置,还是先进入到上面的方法,再添上一个参数后跳到下面那个方法里面

由于get方法,query方法,点进去都是接口,于是没得找了,总不能让我去改框架的代码吧!

 

只能如此了,那么再来一边debug!

一直跑到那个get的方法那里,如图所示:

 

 那么很清楚的是,红线部分看到我们想要拿的那个变量里面,有两个元素!而我们又毛都没拿到,打开瞧瞧里面到底是个啥玩意儿!!!

 显然,这个里面的变量有两个,一个是getUser,另一个是mapper.UserMapper.xml.getUser

就是没有我们在上面提出要找的那个叫做 mapper.UserMapper.getUser 的变量!!

那么我们缓一下调取方法的参数,改成这里面的随意一个,是不是就可以了呢 ?

试试看!

 

 成功了! 这样是可行的!

再来试试另一个变量

 

又成功了!也是可以的!

那么问题来了,为什么呢?

首先,我特么为什么要写跟namespace里面一样的名字呢?

因为我以前没有搞过这个玩意儿,惭愧,我特么全是抄的别人的demo,

本来是想着好歹跑通第一个程序先,但是我不知道为什么,别人的代码能跑通,我就怎么也跑不通,忧伤加惆怅了很久!

找也找不到解决办法,于是就迫不得已自己干了,于是有了这篇博文!

 

再次,对于这个问题的结论是啥呢?

对一个mapper的xml文件,要是想引用一个方法,有两个途径:

 

一、参数直接传那个方法的名字,即定义的id值,上图中1的部分(当然,可能前提是添加了上文提到的build部分的代码才可以!)

二、参数传 namespace+id的值,即上图中1和2的拼接,结果为mapper.UserMapper.xml.getUser

测试结果,上文已经有了!

 

 

——————————————————————————————————————————————————————

写在最后,

最为一个小菜鸡,我时常靠着很多大佬的博文解决了海量问题,这些博文都实实在在地提升了我的工作能力,知识水平,更甚至提升了整个程序员群体的工作效率和知识储备,是几乎程序员群体以另一种形式推动着行业的发展。

毕竟,再牛逼的人,解决哪怕再小的问题,都是需要时间的!

这些海量的博文,将许许多多前人工作过的成果以及思考过程,涉及到的知识内容,直接分享了出来,节省了巨大的时间!

 

  这篇博文,说到底就是一个入门级debug过程,

  但是我在搜到了天知道多少博文,千篇一律,不仅仅不节省时间,反而浪费了时间,其中以csdn的博文特别多,感觉这是一个相当不好的现象,简直是行业倒退,感觉非常不好。

  由于本人自己并没有输出多少高质量的博文,着实惭愧!

  鉴于自己写了上面的一段似乎很正直的话,而这样的博文也有益于自己,有益于行业,

  本菜鸡以后会多多反思,多多总结,为整个行业的解决方案和节省时间大业,添砖加瓦!

  争取以后多多输出高质量的博文

  共勉!

 

posted @ 2019-06-22 18:10  thinfog  阅读(1300)  评论(0编辑  收藏  举报