MyBatis 框架学习(II)

MyBatis 框架学习(II)

文章目录

  • MyBatis 框架学习(II)
    • 1. 介绍
    • 2. 准备&测试
      • 2.1 配置数据库连接字符串和MyBatis
      • 2.2 编写持久层代码
    • 3. MyBatis XML基础操作
      • 3.1 Insert 操作
      • 3.2 Delete 操作
      • 3.3 Update 操作
      • 3.4 Select 操作
    • 4. #{} 与 ${}的使用
    • 5. 动态SQL操作
      • 5.1 < if >标签
      • 5.2 < trim >标签
      • 5.3 < where >标签
      • 5.4 < set >标签
      • 5.5 < foreach >标签
      • 5.6 < include >标签
    • 总结

在上一篇文章中,我们学习了通过 注解的方式( MyBatis 框架学习(I) )来进行 MyBatis开发,接下来我们来学习使用 XML的方式进行 MyBatis开发:

1. 介绍

使用MyBatis注解的方式主要是用来解决简单的SQL操作,如增删改查功能,如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件

2. 准备&测试

想要进行XML的使用,我们需要先完成以下配置:

  • 配置数据库连接字符串和MyBatis;
  • 编写持久层代码

2.1 配置数据库连接字符串和MyBatis

如果配置文件是application.properties,代码如下:

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_test
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=123456

#配置mybatis的日志, 指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#开启mybatis的驼峰命名自动映射开关 a_column ------> aCloumn
mybatis.configuration.map-underscore-to-camel-case=true

# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件 --> 使用XML需要配置这个
mybatis.mapper-locations=classpath:mapper/**Mapper.xml

如果配置文件是application.yml,代码如下:

# 数据库连接配置 每个空格都不能省略,yml严格要求格式正确
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
# 配置打印 MyBatis⽇志
mybatis:
 configuration:
 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

mybatis:
 configuration:
 map-underscore-to-camel-case: true #配置驼峰⾃动转换
 
# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
mybatis:
 mapper-locations: classpath:mapper/**Mapper.xml

2.2 编写持久层代码

持久层代码分两部分:

  1. 方法定义:Interface
  2. 方法实现:XXX.xml

在这里插入图片描述

首先需要定义mapper接口

@Mapper
public interface UserInfoXmlMapper {
    // 查询所有用户
    public List<UserInfo> queryAllUser();
    
}

之后创建xml文件

在这里插入图片描述

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="org.example.blog_mybatis.mapper.UserInfoXmlMapper">
    <select id="queryAllUser" resultType="org.example.blog_mybatis.pojo.UserInfo">
        select username, password, id, username, 
               password, age, gender, phone, delete_flag, 
               create_time, update_time from userinfo
    </select>
</mapper>

对上述内容进行分析:

  • <mapper>标签:需要指定namespace属性,表示命名空间,值为mapper接口的全限定名称,即包括全包名.类名,可以通过以下方式直接获取:

    在这里插入图片描述

  • < select >标签:查询标签,用于进行数据库中的查询操作:

    • id是和mapper接口中定义的方法名称一致,表示对接口的具体实现方法;
    • resultType:返回的数据类型,也就是我们定义的实体类(也需要为全限定名称)

在这里插入图片描述

最后编写测试代码:

package org.example.blog_mybatis.mapper;

import org.example.blog_mybatis.pojo.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class UserInfoXmlMapperTest {

    @Autowired
    private UserInfoXmlMapper userInfoXmlMapper;

    @Test
    void queryAllUser() {
        List<UserInfo> list = userInfoXmlMapper.queryAllUser();
        System.out.println(list);
    }
}

在这里插入图片描述

测试成功!!

3. MyBatis XML基础操作

3.1 Insert 操作

UserInfoXmlMapper中进行方法定义:

Integer InsertUser(UserInfo userInfo);

之后在XML文件中进行方法实现:

<insert id="InsertUser">
    insert into userinfo(username, password, age, phone, gender)
    values (#{username}, #{password}, #{age}, #{phone}, #{gender})
</insert>

编写测试方法:

@Test
void insertUser() {

    UserInfo userInfo = new UserInfo();
    userInfo.setUsername("飞天虎");
    userInfo.setPassword("125");
    userInfo.setAge(38);
    userInfo.setGender(1);
    userInfo.setPhone("100");
    Integer count = userInfoXmlMapper.InsertUser(userInfo);
    System.out.println("添加数据条数:" + count);
}

在这里插入图片描述

在这里插入图片描述

如果使用@Param设置参数名称的话,使用方法和注解类似,同时若需要获取ID,可以在insert标签中添加属性useGeneratedKeyskeyProperty

<insert id="InsertUser" useGeneratedKeys="true" keyProperty="id" >
    insert into userinfo(username, password, age, phone, gender)
    values (#{username}, #{password}, #{age}, #{phone}, #{gender})
</insert>

在这里插入图片描述

3.2 Delete 操作

UserInfoXmlMapper中进行方法定义:

void DeleteUser(Integer id);

之后在XML文件中进行方法实现:

<delete id="DeleteUser">
    delete from userinfo where id = #{id}
</delete>

编写测试方法:

@Test
void deleteUser() {
    userInfoXmlMapper.DeleteUser(14);
}

在这里插入图片描述

在这里插入图片描述

3.3 Update 操作

UserInfoXmlMapper中进行方法定义:

Integer UpdateUser(UserInfo userInfo); 

之后在XML文件中进行方法实现:

<update id="UpdateUser">
    update userinfo set username = #{username}, age = #{age} where id = #{id}
</update>

编写测试方法:

@Test
void updateUser() {
    UserInfo userInfo = new UserInfo();
    userInfo.setId(12);
    userInfo.setUsername("张三丰");
    userInfo.setAge(100);
    Integer count = userInfoXmlMapper.UpdateUser(userInfo);
    System.out.println("修改数据:" + count);
}

在这里插入图片描述

在这里插入图片描述

3.4 Select 操作

UserInfoXmlMapper中进行方法定义:

UserInfo queryUser(Integer id);

之后在XML文件中进行方法实现:

<select id="queryUser" resultType="org.example.blog_mybatis.pojo.UserInfo">
    select id, username, password, age, 
           gender, phone, delete_flag, 
           create_time, update_time from userinfo where id = #{id}
</select>

编写测试方法:

@Test
void queryUser() {
    UserInfo userInfo = userInfoXmlMapper.queryUser(5);
    System.out.println(userInfo);
}

在这里插入图片描述

:这里能够正确的获取到全部数据是因为在配置文件里配置了自动进行驼峰命名,若没有添加这个配置则返回结果中后续几个属性值(deleteFlag开始)会为null,如何添加在上篇文章有介绍:[MyBaits 框架学习(I)]

4. #{} 与 ${}的使用

在前面我们使用#{}来进行参数传递,#{}本身属于预编译SQL机制,通过?占位的方式提前对SQL进行编译,然后把参数填充到SQL语句中,如下:

在这里插入图片描述

如果传进来的是String类型的参数,#{}也会根据类型自动添加引号

${}即时SQL,它的作用就是将参数直接拼接到SQL语句中:

在这里插入图片描述

如果传入的参数是字符串的话,需要手动给它添加上引号,否则传入${}的参数不会自动添加引号,进而报错,比如通过名称查询用户信息,若xml代码这样写:

<select id="queryUserByName" resultType="org.example.blog_mybatis.pojo.UserInfo">
    select id, username, password, age,
           gender, phone, delete_flag,
           create_time, update_time from userinfo where username = ${username}
</select>

在这里插入图片描述

可以看到运行结果会报错,此时就需要我们手动给${}添加引号:

<select id="queryUserByName" resultType="org.example.blog_mybatis.pojo.UserInfo">
    select id, username, password, age,
           gender, phone, delete_flag,
           create_time, update_time from userinfo where username = '${username}'
</select>

在这里插入图片描述

此时查询结果就正确了

5. 动态SQL操作

MyBatis为我们提供了一个强大的功能来解决复杂的SQL操作,那就是动态SQL,它能够完成不同条件下不同的sql拼接,接下来我们来学习相应的标签:

5.1 < if >标签

当我们需要根据特定条件进行语句判断时即可以使用if标签,比如之前通过Insert操作向数据库插入用户信息:

<insert id="InsertUser" useGeneratedKeys="true" keyProperty="id" >
    insert into userinfo(username, password, age, phone, gender)
    values (#{username}, #{password}, #{age}, #{phone}, #{gender})
</insert>

如果这个时候性别是非必填字段,希望根据用户有无传入这个属性来让sql编译时自动添加gender这个字段,则可以使用if标签来进行判断:

<insert id="InsertUser" useGeneratedKeys="true" keyProperty="id" >
    insert into userinfo(
            username,
            password,
            age,
            phone,
         <if test="gender != null">
            gender
         </if>
         )
    values (#{username},
            #{password},
            #{age},
            #{phone},
         <if test="gender != null">
            #{gender}
         </if>
        )
</insert>

在这里插入图片描述

此时因为没有传入gender参数所以sql语句编译时没有显示gender字段

5.2 < trim >标签

在上面的if语句中,其实存在着一个隐藏的问题,那就是字段后面的逗号(","),如果我的gender属性为null,则上述phone字段后面跟着的逗号也会一起被sql语句编译,这个时候就会出现问题了:

在这里插入图片描述

这个时候我们可以通过trim标签来解决这个问题:

insert into userinfo(
        <trim suffixOverrides=",">username,
                password,
                age,
                phone,
                <if test="
        gender != null">
                    gender
                </if>
                
            </trim>
        )
    values (
            <trim suffixOverrides=",">
                #{username},
                #{password},
                #{age},
                #{phone},
                <if test="gender != null">
                    #{gender}
                </if>
            </trim>
        )
</insert>

在这里插入图片描述

对于trim标签,它有以下属性:

  • prefix:表示整个语句块(从<trim>到</trim>),以prefix的值为前缀;
  • suffix:表示整个语句块,以suffix的值为后缀;
  • prefixOverrides:表示整个语句块要除掉的前缀;
  • suffixOverrides:表示整个语句块要除掉的后缀,比如上述代码中的","

在一般情况下,当我们需要对多个字段进行动态生成时即可使用trim标签

5.3 < where >标签

<where>标签只会在子元素有内容的情况下才会插入where子句,而且会自动去除子句开头的 ANDOR:

先在UserInfoXmlMapper中进行方法定义:

List<UserInfo> queryUserByCondition(Integer age, Integer gender, Integer deleteFlag);

之后在XML文件中进行方法实现:

<select id="queryUserByCondition" resultType="org.example.blog_mybatis.pojo.UserInfo">
    select username, password, id, username,
    password, age, gender, phone, delete_flag,
    create_time, update_time from userinfo
    <where>
        <if test="age != null">
            and age = #{age} 
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
        <if test="deleteFlag != null">
            and delete_flag = #{deleteFlag}
        </if>
    </where>
</select>

编写测试方法:

@Test
void queryUserByCondition() {
    List<UserInfo> list = userInfoXmlMapper.queryUserByCondition(18, 1,0);
    System.out.println(list);
}

在这里插入图片描述

test属性对应的参数为方法传入参数而不是字段名,且如果方法传入参数为空,where标签中子元素无内容,不会插入子句:

在这里插入图片描述

5.4 < set >标签

当我们需要根据用户传入的信息来修改内容时,可以通过set标签实现动态修改,如修改参数不为null的属性:

<update id="UpdateUser">
    update userinfo
        <set>
            <if test="username != null">
                username = #{username}
            </if>
            <if test="age != null">
                age = #{age},
            </if>
            <if test="deleteFlag != null">
                delete_flag = #{deleteFlag}
            </if>
        </set>
    where id = #{id}
</update>

在这里插入图片描述

set标签用于update语句中,并且会删除额外的逗号,以上标签也可以使用替换

5.5 < foreach >标签

当我们需要对集合进行遍历时可以使用该标签,foreach标签有以下属性:

  • collection:绑定方法参数中的集合,如List,Set,Map或数组对象;
  • item:遍历时的每一个对象;
  • open:遍历开始时加的前缀;
  • close:遍历结束时加的后缀;
  • separator:每次遍历之间间隔的字符串

如果我们现在需要批量删除用户信息,就可以使用foreach标签进行遍历删除,代码如下:

UserInfoXmlMapper中进行方法定义:

void DeleteUserById(List<Integer> ids);

之后在XML文件中进行方法实现:

<delete id="DeleteUserById">
    delete from userinfo
    <where>
        id in
        <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </where>
</delete>

编写测试代码:

void deleteUserById() {
    List<Integer> list = new ArrayList<>();
    list.add(15);
    list.add(16);
    list.add(17);
    userInfoXmlMapper.DeleteUserById(list);
}

在这里插入图片描述

在这里插入图片描述

5.6 < include >标签

XMl文件中配置sql,有时候会出现许多重复的字段,这样会造成一定的代码冗余:

在这里插入图片描述

对此,我们可以对重复的代码进行抽取,将其通过<sql>标签封装到一个SQL片段中,然后再通过<include>标签进行引用:

  • <sql>:定义可重复的SQL片段;
  • <include>:通过属性refid,指定包含的SQL片段

在xml文件中添加:

<sql id="allColum">
    id, username, password, age,
    gender, phone, delete_flag,
    create_time, update_time
</sql>

通过标签引用重复sql片段,且rafid属性的值与sql标签中id的属性值相同

<select id="queryUser" resultType="org.example.blog_mybatis.pojo.UserInfo">
    select <include refid="allColum"></include> from userinfo where id = #{id}
</select> 

在这里插入图片描述

总结

对于MyBatis XML方式的使用就介绍到这,对于注解和XML两者的使用范围并不固定,推荐在进行简单的SQL操作时可以使用注解更加方便快捷,而对于复杂的SQL操作则可以使用XML的方式来进行高效解决!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/561181.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

4.2冰达机器人:视觉实例-机器人视觉循线、视觉实例-调整循线颜色

4.2.10a视觉实例-机器人视觉循线 本节内容演示一个机器人视觉的视觉循线实例 准备工作&#xff1a;布置一块区域作为循线场所&#xff0c;如下图所示。用蓝色胶带在地面贴一条路线&#xff08;机器人极限转弯半径0.5m&#xff0c;不要贴得过于曲折&#xff09;&#xff0c;将…

leetcode:438. 找到字符串中所有字母异位词

给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 示例 1: 输入: s "cbaebabacd", p "…

形态学初步

其实在考虑集合的位移z的时候我发现了个问题&#xff0c;以书上的图9.4为例子。现实中&#xff0c;位移z不需要坐标系&#xff0c;但是实际上&#xff0c;不给出坐标系描述位移量是不方便的。其次&#xff0c;位移的前提是需要一个起始位置&#xff0c;但是起始位置如何建立呢&…

Docker - HelloWorld

原文地址&#xff0c;使用效果更佳&#xff01; Docker - HelloWorld | CoderMast编程桅杆https://www.codermast.com/dev-tools/docker/docker-helloworld.html 开始之前 在学习本小节之前&#xff0c;你必须确保你正确安装了 Docker&#xff0c;正确安装 Docker 是后续学习的…

.net8系列-02图文并茂手把手教你编写增删改查接口

前情提要 接上篇文章&#xff0c;我们的应用已经创建完毕了&#xff0c;接下来我们编写几个自己的接口 快速开始 新增Controller 复制一份WeatherForecastController.cs,改名为CommonInfoController 设置Class名 将CommonInfoController中的复制过来的class名改成新名 …

.NET .exe .dll 反编译 程序反编译 程序逆向

反编译是对程序进行逆向分析、研究&#xff0c;以推导出软件产品所使用的思路、原理、结构、算法、处理过程、运行方法等设计要素。 反编译.NET程序需要使用专门的反编译工具 &#x1f9ff;使用dotPeek进行反编译 1.下载dotPeek dotPeek&#xff1a;JetBrains 出品的免费 .N…

[阅读笔记25][WebArena]A Realistic Web Environment for Building Autonomous Agents

这篇论文提出了WebArena这个环境与测试基准&#xff0c;在24年1月发表。 之前的agent都是在一些简化过的合成环境中测试的&#xff0c;这会导致与现实场景脱节。这篇论文构建了一个高度逼真、可复现的环境。该环境涉及四个领域&#xff1a;电子商务、论坛讨论、软件开发和内容管…

【linux运维】系统常见管理命令

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了学习基本的shell编程和linux命令&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于b站大学——linux运维课程进行的&#xff0c;…

数据结构 -- 二叉树二叉搜索树

二叉树 二叉树是这么一种树状结构&#xff1a;每个节点最多有两个孩子&#xff0c;左孩子和右孩子 重要的二叉树结构 完全二叉树&#xff08;complete binary tree&#xff09;是一种二叉树结构&#xff0c;除最后一层以外&#xff0c;每一层都必须填满&#xff0c;填充时要遵…

自然语言处理基础面试

文章目录 TF-IDFbag-of-wordsBert 讲道理肯定还得有Transformer&#xff0c;我这边先放着&#xff0c;以后再加吧。 TF-IDF TF&#xff08;全称TermFrequency&#xff09;&#xff0c;中文含义词频&#xff0c;简单理解就是关键词出现在网页当中的频次。 IDF&#xff08;全称…

【C++初识继承】

博主首页&#xff1a; 有趣的中国人 专栏首页&#xff1a; C进阶 本篇文章主要讲解 继承 的相关内容 目录 1. 继承的概念和定义 1.1 继承的概念 1.2 继承的定义 1.2.1 继承定义格式 1.2.2 继承方式与访问修饰限定符 2. 基类和派生类对象赋值转换 3. 继承中的作用域 …

读天才与算法:人脑与AI的数学思维笔记05_算法的幻觉

1. 自下而上 1.1. 代码在未来可以自主学习、适应并进行自我改进 1.2. 程序员通过编程教会计算机玩游戏&#xff0c;而计算机却会比教它的人玩得更好&#xff0c;这种输入寡而输出众的事情不大可能实现 1.3. 早在20世纪50年代&#xff0c;计算机科学家们就模拟该过程创造了感…

内存概念理解:RANK,BANK,BURST,INTERLEAVING

背景&#xff1a;死磕内存的bank和rank概念的一天。网上的资料都差不多&#xff0c;还是有些地方没理通顺&#xff0c;有什么内存基础知识的书籍可以推荐吗&#xff1f; 物理RANK的概念 当我们给计算机购买内存条时候&#xff0c;上面显示的1RX8, 2RX8&#xff0c;其中R就是r…

【ARM 裸机】I.MX 启动方式之启动头文件 1

接上一节&#xff1a;【ARM 裸机】I.MX 启动方式之启动设备的选择&#xff1b; 2、启动头文件 当 BOOT_MODE1 为 1&#xff0c;BOOT_MODE0 为 0 的时候此内部 BOOT 模式&#xff0c;在此模式下&#xff0c;芯片会执 行内部的 BOOT ROM 代码&#xff0c;这段 BOOT ROM 代码会进…

常见的七种排序

目录 一、插入排序 1、直接插入排序 2、希尔排序&#xff08;缩小增量排序&#xff09; 二、选择排序 3、直接选择排序 4、堆排序 三、交换排序 5、冒泡排序 6、快速排序 四、归并排序 7、归并排序 五、总结 一、插入排序 1、直接插入排序 思路&#xff1a; i 用来…

Xamarin.Android中“ADB0020: Android ABI 不匹配。你正将应用支持的“armeabi-v7a;arm64-v8a”异常处理

这里写自定义目录标题 1、问题2、解决 1、问题 在Xamarin.Android中出现ADB0020: Android ABI 不匹配。你正将应用支持的“armeabi-v7a;arm64-v8a”ABI 部署到 ABI“x86_64;x86”的不兼容设备。应创建匹配其中一个应用 ABI 的仿真程序&#xff0c;或将“x86_64”添加到应用生成…

Parade Series - CoreAudio Loopback

Scenario 鉴于业务场景需要&#xff0c; 经过技术路径探索&#xff0c; 发现 comtypes 兼容性过于混乱&#xff0c;故而考虑整合一个 CoreAudio 的轮子dll来解决实际问题&#xff01;std::StringStream ⇒ std::ios::binary ⇒ std::ofstream Loopback.dll #ifndef _DLL_C…

【nvm最新解决方案】Node.js v16.20.2 is not yet released or available

【nvm最新解决方案】Node.js v16.20.2 is not yet released or available 解决办法&#xff1a;下载想安装的node压缩包&#xff0c;放入nvm对应目录。 2024年最新node压缩包地址&#xff1a;https://nodejs.org/dist/ 1、选择对应的node版本&#xff1a;例如&#xff0c;我选的…

如何创建响应式HTML电子邮件模板

在这个适合初学者的指南中&#xff0c;你将学习如何创建一个响应式电子邮件模板。你将跟随逐步说明以及代码片段设计一个在任何设备上都看起来很棒的电子邮件模板。 这个项目非常适合渴望掌握电子邮件设计基础的新手&#xff01; &#xff08;本文视频讲解&#xff1a;java56…

怎么用手机远程控制电脑 远程控制怎么用

怎么用手机远程控制电脑&#xff1a;远程控制怎么用 在这个科技日新月异的时代&#xff0c;远程控制电脑已经成为了很多人的需求。有时&#xff0c;我们可能在外出时突然需要访问家中的电脑&#xff0c;或者在工作中需要远程操控办公室的电脑。这时&#xff0c;如果能用手机远…