Mybatis XML映射文件:查询元素解析+案例+个人玩转参数问题案例详解

2023-05-16

文章目录

  • 🕊前言
  • 🕊查询元素select
    • 常用的属性
    • 案例
  • 🕊insert, update 和 delete
    • 参数
    • 案例
    • 注意点
  • 🕊sql元素
  • 🕊参数
    • 情景一:省略parameterType(无注解情况)
      • 下面是针对输入一个参数的测试
      • 输入两个参数
    • 顺序映射方式(不使用注解和map)
      • 小结
    • 情景二:使用注解
      • 小结
    • 使用map

🕊前言

MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。

下面介绍的都是元素比较常用的属性,如若想要了解更多属性,欢迎点击Mybatis3中文官方文档
以下所有的解析使用的数据库表为user表,以下为数据:

在这里插入图片描述

🕊查询元素select

常用的属性

id在命名空间中唯一的标识符,可以被用来引用这条语句。 id的值一般和DAO接口的方法名一致,如果不唯一或者不一致,MyBatis将抛出异常!
parameterType将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
resultType期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。
resultMap对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。

案例

1、查询所有用户
UserMapper接口

//    查询所有用户
    List<User> getUserList();

UserMapper.xml

    <select id="getUserList" resultType="com.xmonster.pojo.User">
        select * from mybatis.user
    </select>

注意返回值的类型写法

2、根据id查询某用户

UserMapper接口

//    根据id查询某用户
    User getUserId(int id);

UserMapper.xml

    <select id="getUserId" parameterType="int" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where id=#{id}
    </select>

3、模糊查询
注意:Java代码执行的时候,传递通配符%
UserMapper接口

//    模糊查询
    List<User> getUserLike(String value);

UserMapper.xml

    <select id="getUserLike" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where name like "%"#{value}"%";
    </select>

🕊insert, update 和 delete

参数

属性描述
id在命名空间中唯一的标识符,可以被用来引用这条语句。 在命名空间中唯一的标识符,可以被用来引用这条语句。 id的值一般和DAO接口的方法名一致,如果不唯一或者不一致,MyBatis将抛出异常!
parameterType将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。
useGeneratedKeys(仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。
keyProperty(仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。
keyColumn(仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。

案例

UserMapper.java

//    插入用户
    int addUser(User user);
//    万能的map插入
    int addUser2(Map<String, Object> map);
//    更新用户
    int updateUser(User user);
//    万能map修改用户密码
    int updateUser2(Map<String, Object> map);
//    删除用户
    int deleteUser(int id);

UserMapper.xml

  <insert id="addUser" parameterType="com.xmonster.pojo.User" >
        insert into mybatis.user (id,name ,pwd) values (#{id}, #{name}, #{pwd})
    </insert>
    
<!--    万能map,values后面的#{},括号里的值可以不用和User对象的属性名一一对应,反正传递的时map的key值-->
    <insert id="addUser2" parameterType="map" >
        insert into mybatis.user (id,name ,pwd) values (#{userId}, #{userName}, #{Password})
    </insert>

    <update id="updateUser" parameterType="com.xmonster.pojo.User">
        update mybatis.user set name=#{name}, pwd=#{pwd} where id=#{id}
    </update>

<!--    万能map修改用户密码-->
    <update id="updateUser2" parameterType="map">
        update mybatis.user set pwd=#{Password} where id=#{userId}
    </update>

    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{id}
    </delete>

test.java

//add
    @Test
    public void test1(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);//得到接口
        int blue = mapper.addUser(new User(4, "blue", "19334"));
        sqlSession.commit();
        sqlSession.close();
    }
//map 插入
    @Test
    public void test2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        Map<String, Object> map = new HashMap<>();
        map.put("userId", 4);
        map.put("userName", "aa");
        map.put("Password", "444444");
        mapper.addUser2(map);
        sqlSession.commit();
        sqlSession.close();
    }
 //更新
    @Test
    public void test3(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        mapper.updateUser(new User(4,"red","222222"));
        sqlSession.commit();
        sqlSession.close();
    }
 //map指定元素更新    
     @Test
    public void test4(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        Map<String, Object> map = new HashMap<>();
        map.put("userId", 4);
        map.put("Password", "333333");
        mapper.updateUser2(map);
        sqlSession.commit();
        sqlSession.close();
    }
 //删除用户
       @Test
    public void test5(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        mapper.deleteUser(4);
        sqlSession.commit();
        sqlSession.close();
    }

注意点

每次使用增删改查之后,不要忘记提交事务:sqlSession.commit();
也可以选择在(一般放在工具类里)MybatisUtils里,也就是生成sqlsession的函数中,在执行返回值的时候,参数选择true,这样每次你执行的时候都会自动提交事务:

public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);
    }

🕊sql元素

对重复的sql语句进行组装起来,使用SQL标签抽取公共部分,在需要使用的地方include即可。下面是个例子,没有任何前后逻辑,就是单纯的例子:
Mapper.xml:

    <sql id="if-title-author">
        <if test="title != null">
            and title=#{title}
        </if>
        <if test="author != null">
            and author=#{author}
        </if>
    </sql>
<!--    查询博客-->
    <select id="queryBolg" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
         <include refid="if-title-author"></include>
        </where>
    </select>

用标签引入,refid填sql片段的id即可
抽取的原则

  1. 最好基于单表来定义SQL片段!
  2. 不要存在where标签,把where丢进去就没啥用了,去想想什么才叫复用

🕊参数

MyBatis 的其它部分一样,几乎总是可以根据参数对象的类型确定 javaType,除非该对象是一个 HashMap,这个时候,你需要显式指定 javaType 来确保正确的类型处理器(TypeHandler)被使用。

情景一:省略parameterType(无注解情况)

传入的参数是简单的int类型,就比如上面的根据id查询用户信息,其实我也可以不用写parameterType,系统会自动的进行匹配,甚至在Mapper.xml里#{}括号里的参数也可以和接口参数名字不一致,

下面是针对输入一个参数的测试

Mapper.xml:

    <select id="getUserId" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where id=#{uid}
    </select>

在这里插入图片描述
上面的这个示例说明了一个非常简单的命名参数映射。鉴于参数类型(parameterType)会被自动设置为 int,这个参数可以随意命名
但是这里只是针对这种非常简单的情况,这里的简单是指首先查询语句简单,其次就是传递的参数很简单,但是原始类型简单数据类型(比如 Integer 和 String)因为没有其它属性,会用它们的值来作为参数。
再来一次测试
需求:输入用户的名字,输出对应用户的所有信息
UserMapper接口

//    根据输入用户的名字输出对应用户信息
    User getUserName(String name);

UserMapper.xml

    <select id="getUserName" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where name=#{uname}
    </select>

在这里插入图片描述
但是为了规范,#{}括号里的参数最好和接口参数名称一致,就不要向上面一样又是id,又是uid

输入两个参数

这里就有要注意的点了,先来看一下代码
UserMapper接口

//    根据输入的用户姓名和密码查找对应的用户信息
    User getUserByNamePwd(String name, String pwd);

UserMapper.xml

    <select id="getUserByNamePwd" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where name=#{name} and pwd=#{pwd};
    </select>

test.java

    @Test
    public void test9(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);//得到接口
        User userId = mapper.getUserByNamePwd("xmonster","123456");
        System.out.println(userId);
        sqlSession.close();
    }

结果发现报错:
在这里插入图片描述

顺序映射方式(不使用注解和map)

原因:在Mybatis中当映射器需要多个参数的时候,有三种方法,一种是需要是需要导包的,这里与其说是要导包不如说是要用注解来解决问题;还有map;还有一种就是使用它默认的参数,这也就是顺序映射方式
我们只需要改变XML配置当中的参数即可,但是我们一般如果说是多参数,又不想用注解,又不想用map,就是想要单纯的两个参数来达到目的的话,一般这几个参数的参数类型都是同一个类型
就如果说你想通过id和name去查用户信息,id和name一个是int,一个是String,那么你的parameterType就不好写,简单来说也没人会这么用,除非这几个参数是同一个类型,或者你传入的参数是一个对象,不过在输入的时候你就要三个属性都输入,显然这和我只想要输入两个参数的目的不符
举个例子,想要通过输入用户名字和密码查询该用户所有信息,就只输入两个参数,不输入id的情况
UserMapper接口

//    输入用户id和名字,输出对应的用户的信息
    User getUserNamePwd(String name, String Pwd);

UserMapper.xml

    <select id="getUserNamePwd" parameterType="String" resultType="com.xmonster.pojo.User">
        select * from mybatis.user where name =#{param1} and pwd=#{param2}
    </select>

test.java

    @Test
    public void test9(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);//得到接口
        User user = mapper.getUserNamePwd("xmonster", "123456");
        System.out.println(user);
        sqlSession.close();
    }

测试发现通过:
在这里插入图片描述

小结

顺序映射方法其实使用的情况比较少,可以看到在Mapper.xml中参数用的是param1 param2这也和上面的报错信息一致,旧版本的Mybatis用的是#{0} #{1}进行映射的

情景二:使用注解

先解决一下上面的问题
直接修改
UserMapper接口

//    根据输入的用户姓名和密码查找对应的用户信息
    User getUserByNamePwd(@Param("id") int id, @Param("name") String name, @Param("pwd") String pwd);

其他不变,可以看到,我们成功查出
在这里插入图片描述
当然了使用注解就可以不用管多少个参数了,参数类型一不一致了,在传参的时候Mapper.xml文件中#{}括号里写入的参数是@Param里的,而不是你自己定义的参数名字
比如

//    根据输入的用户姓名和密码查找对应的用户信息
User getUserByNamePwd(@Param("uid") int id, @Param("uname") String name, @Param("upwd") String pwd);

那么在Mapper.xml中就只认得uid/uname/upwd,传参时注意

小结

关于@param()注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不用加
  • 如果只有一个基本类型,可以忽略,但是建议大家都加上!
  • 我们在SQL中引用的就是我们这里的@Param()中设定的属性名!

使用map

使用ma直接看上方案例即可。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mybatis XML映射文件:查询元素解析+案例+个人玩转参数问题案例详解 的相关文章

  • 如何将 Xml 文件转换为文本文件 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有大约 8000 个 xml 文件需要转换为文本文件 文本文件必须包含 xml 文件的标题 描述和关键字 不含标签 并删除其他元素和
  • magento 删除管理菜单项

    在magento中 是否可以删除管理中的菜单项 我有一个新模块 并将评论和评级拉到一个新部分 我不反对将它们也留在目录部分 但如果可能 并且干净 我想将其从那里删除 将下一行添加到扩展 config xml 文件
  • SQL Server 2008 XPath

    我们尝试根据我们提供的值过滤一组 XML 我们的数据库的 XML 字段中有以下 XML 如果传递数字 5052095050830 我们需要在 XML 中找到这个特定节点 我们提供的号码可能存在任意多次 任何机构都可以提供一些 SQL 示例来
  • MyBatis 映射中的复合键

    我无法将组合键传递给 MyBatis
  • 使用字符串数组填充 Spinner

    当谈到 Android 应用程序时 我属于新手联盟 我希望用数组或字符串填充 Spinner 它是一个转换器应用程序 下面是我的 XML 文件的摘录 我希望填充 Spinner
  • 将 XML 数据提取到 php [重复]

    这个问题在这里已经有答案了 我正在尝试从 XML 文件中提取数据 http freegeoip net xml google com http freegeoip net xml google com 您可以看到该文件的内容类似于
  • Xslt 到 xsl-fo 转换

    我想将 xslt 转换为 xsl fo 但我不太确定我能做到这一点 我尝试将 XML 列表转换为 xsl fo 列表 谁能告诉我在哪里可以找到我在谷歌上搜索了很长时间没有很多这样的例子 我的XML是这样的 p TEXT p ul li It
  • 膨胀类片段 InflateException 二进制 XML 文件时出错

    我正在使用 Material Design 和 NavigationDrawer 布局等设计我的第一个应用程序 但我遇到了一个问题 该应用程序非常简单 它只显示文本 并且基于 Android Studio 中提供的模板 尝试启动我的应用程序
  • Android 键盘清单未显示在设置中

    我正在制作我的第一个 Android 应用程序 我需要它作为键盘服务 据我所知 清单看起来不错 并且我有一个文件 WifiJoy java 在 com zwad3 wifijoy 包中 以及所有其他文件
  • 使用 JAXB 编组只能包含多种子节点类型之一的 XML 节点(SharePoint 查询)

    我正在尝试创建 JAXB 带注释的类来生成基于 Microsoft SharePoint 的 XML查询模式 http msdn microsoft com en us library ms467521 28v office 14 29 a
  • 什么时候应该使用 XML 而不是 SQL? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 具有挑战性的问题 - 使用 PHP 对 XML 数据进行排序

    我有 xml 文件 其中包含大量产品数据 我需要根据我的字段 ProductRange 的数据对我的产品进行排序 ProductRange urldecode GET Range XML 文件数据
  • jQuery - 提高处理 XML 时的选择器性能

    我正在处理一个 XML 文件 当使用 XPath 样式选择器选择节点时 该文件的性能非常慢 这是运行特别慢的部分代码 for i 0 i
  • 在python中读取PASCAL VOC注释

    我在 xml 文件中有注释 例如这个 它遵循 PASCAL VOC 约定
  • 在线性布局内的 ScrollView 内并排对齐 TextView

    我有一个带有滚动视图的线性布局 我想保留它的当前格式 但只需将 textView2a 和 textView3a 并排放置 而不会破坏我当前的布局格式 我已经包含了我最近的尝试 但它们似乎不正确 提前致谢 Java菜鸟 当前有效的 XML
  • PHP 和 DOM 文档

    我有一个关于 DOMDocument 的使用和创建 XML 的问题 我有一个 PHP 程序 加载到 XML 文件中 处理XML的每个节点 行 将其发送到另一个进程 然后该进程返回一个 XML 元素 我获取节点的字符串表示形式 以便可以创建
  • JavaFX 中的 fx:id 和 id: 有什么区别?

    也许是一个真正的新手的问题 我开始通过阅读以下教程在 FMXL 应用程序中使用场景生成器学习 JavaFX http docs oracle com javase 8 javafx get started tutorial fxml tut
  • XPath 中的 ., 有什么用?

    为什么在某些 XPath 表达式中句号后面使用逗号 这是一个例子 Set nlist doc selectNodes book author first name starts with M 我试图用谷歌搜索这个 但字面意思 运算符似乎不喜
  • 如何去除 XSL 中字符的重音符号?

    我一直在寻找 但找不到相当于字符 规范化空间 的 XSL 函数 也就是说 我的内容带有重音 UNICODE 字符 这很好 但是从该内容中 我正在创建一个文件名 但我不想要这些重音 那么 是否有一些我忽略的东西 或者没有正确地谷歌搜索来轻松处
  • 简单的 Xml - 元素的顺序未保留?

    我在我的 Android 应用程序中使用 SimpleXml 2 6 1 尽管文档 http simple sourceforge net download stream doc javadoc index html org simplef

随机推荐