zoukankan      html  css  js  c++  java
  • 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()+"	用户名称:"+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:javainjava.exe "-javaagent:D:IDEIntelliJ IDEA 2019.1.1libidea_rt.jar=53832:D:IDEIntelliJ IDEA 2019.1.1in" -Dfile.encoding=UTF-8 -classpath D:javalibant-javafx.jar;D:javalibdeploy.jar;D:javalibjava.jnlp.jar;D:javalibjavafx-swt.jar;D:javalibjavaws.jar;D:javalibjdk.deploy.jar;D:javalibjdk.javaws.jar;D:javalibjdk.plugin.dom.jar;D:javalibjdk.plugin.jar;D:javalibjrt-fs.jar;D:javalibplugin-legacy.jar;D:javalibplugin.jar;D:workspaceservermybatisDemo	argetclasses;D:workspaceservermybatisDemolibspring-aspects-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-aop-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-beans-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-context-support-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-context-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-core-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-instrument-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-instrument-tomcat-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-expression-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-jms-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-messaging-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-jdbc-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-orm-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-oxm-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-test-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-tx-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibcommons-logging-1.2.jar;D:workspaceservermybatisDemolibaopalliance-1.0.jar;C:UsersAndrew.m2
    epositorymysqlmysql-connector-java5.1.8mysql-connector-java-5.1.8.jar;C:UsersAndrew.m2
    epositoryorgmybatismybatis3.5.1mybatis-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:javainjava.exe "-javaagent:D:IDEIntelliJ IDEA 2019.1.1libidea_rt.jar=53890:D:IDEIntelliJ IDEA 2019.1.1in" -Dfile.encoding=UTF-8 -classpath D:javalibant-javafx.jar;D:javalibdeploy.jar;D:javalibjava.jnlp.jar;D:javalibjavafx-swt.jar;D:javalibjavaws.jar;D:javalibjdk.deploy.jar;D:javalibjdk.javaws.jar;D:javalibjdk.plugin.dom.jar;D:javalibjdk.plugin.jar;D:javalibjrt-fs.jar;D:javalibplugin-legacy.jar;D:javalibplugin.jar;D:workspaceservermybatisDemo	argetclasses;D:workspaceservermybatisDemolibspring-aspects-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-aop-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-beans-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-context-support-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-context-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-core-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-instrument-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-instrument-tomcat-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-expression-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-jms-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-messaging-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-jdbc-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-orm-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-oxm-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-test-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibspring-tx-4.3.18.RELEASE.jar;D:workspaceservermybatisDemolibcommons-logging-1.2.jar;D:workspaceservermybatisDemolibaopalliance-1.0.jar;C:UsersAndrew.m2
    epositorymysqlmysql-connector-java5.1.8mysql-connector-java-5.1.8.jar;C:UsersAndrew.m2
    epositoryorgmybatismybatis3.5.1mybatis-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的博文特别多,感觉这是一个相当不好的现象,简直是行业倒退,感觉非常不好。

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

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

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

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

      共勉!

  • 相关阅读:
    P6585 中子衰变
    [APIO2020]有趣的旅途
    CF1354F Summoning Minions
    CF1361C Johnny and Megan's Necklace
    CF1368E Ski Accidents
    CF1458C Latin Square
    CF1368F Lamps on a Circle
    用户和组的管理
    Windows命令
    1
  • 原文地址:https://www.cnblogs.com/thinfog/p/11069843.html
Copyright © 2011-2022 走看看