Mybatis 查询数据库

1. MyBatis 是什么?

MyBatis 是一个优秀的 ORM(对象关系映射) 持久层框架.

  1. 它⽀持⾃定义 SQL、存储过程以及⾼级映射。
  2. MyBatis 去除了⼏乎所有的 JDBC 代码以及设置参数和获取结果集的⼯作。
  3. MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接⼝和 Java POJO(Plain Old Java Objects,普通⽼式 Java 对象)为数据库中的记录。

简单来说 MyBatis 是更简单完成程序和数据库交互的⼯具,也就是更简单的操作和读取数据库⼯具,特点就是很灵活.

我们学习 MyBatis 主要学习两部分:
1. 配置 MyBatis 开发环境
2. 使用 MyBatis 模式和语法操作数据库

2. 创建 MyBatis 项目

2.1 准备工作,创建数据库和数据表

mybatis 测试数据库:

-- 创建数据库
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8mb4;

-- 使用数据数据
use mycnblog;

-- 创建表[用户表]
drop table if exists  userinfo;
create table userinfo(
    id int primary key auto_increment,
    username varchar(100) not null,
    password varchar(32) not null,
    photo varchar(500) default '',
    createtime datetime default now(),
    updatetime datetime default now(),
    `state` int default 1
) default charset 'utf8mb4';

-- 创建文章表
drop table if exists  articleinfo;
create table articleinfo(
    id int primary key auto_increment,
    title varchar(100) not null,
    content text not null,
    createtime datetime default now(),
    updatetime datetime default now(),
    uid int not null,
    rcount int not null default 1,
    `state` int default 1
)default charset 'utf8mb4';

-- 创建视频表
drop table if exists videoinfo;
create table videoinfo(
  	vid int primary key,
  	`title` varchar(250),
  	`url` varchar(1000),
		createtime datetime default now(),
		updatetime datetime default now(),
  	uid int
)default charset 'utf8mb4';

-- 添加一个用户信息
INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES 
(1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);

-- 文章添加测试数据
insert into articleinfo(title,content,uid)
    values('Java','Java正文',1);
    
-- 添加视频
insert into videoinfo(vid,title,url,uid) values(1,'java title','http://www.baidu.com',1);

注: MySQL 5.7 以下版本 需要去掉 default now()
在这里插入图片描述

2.2 添加 MyBatis 相关依赖

在这里插入图片描述

添加完后不要急着启动项目测试:
在这里插入图片描述

因为我们还没有连接数据库,他是找不到路径的

2.3 配置数据库连接字符串 和 MyBatis(保存的 XML 的目录)

2.3.1 配置数据库的连接信息

这里一般我们会用多个配置文件,以便之后在多个平台运行(最少一般都会有两个)
在这里插入图片描述

像这种常用的,自己可以把它保存在能够经常拿到的地方,下次直接粘贴就好了.

# 配置数据库连接
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8
    username: 你的用户名
    password: 你的密码
    driver-class-name: com.mysql.cj.jdbc.Driver
# 当前运行的环境 (配置文件)
spring:
  profiles:
    active: dev

2.3.2 配置 MyBatis 的 XML 保存路径

# 配置 MyBatis xml 保存路径
mybatis:
  mapper-locations: classpath:mybatis/**Mapper.xml

在这里插入图片描述

2.4 使用 MyBatis 的操作模式操作数据库

我们可以先看一下 MyBatis 整体流程:
在这里插入图片描述在这里插入图片描述

2.4.1 添加代码

提前创好对应的包:
在这里插入图片描述

1. model 包下添加实体类
对应数据库添加:

import lombok.Data;

/**
 * 用户实体类
 */
@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private String photo;
    private String createtime;
    private String updatetime;
    private int state;

}

2. 在 mapper 包下定义接口(普通的接口)

import com.example.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;

@Mapper //添加后才能跟 xml 文件对应起来
public interface UserMapper {
    //根据 id 查询用户
    public UserInfo getUserById(@Param("id") Integer id);
}

3. 创建 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="com.example.demo.mapper.UserMapper">
   
</mapper>

在 resources 的 mybatis 底下新建 UserMapper.xml:(xml 里的名字建议跟 mapper 包下的名字对应一样,这样容易我们观察)

在这里插入图片描述

MyBatis 执行过程:
在这里插入图片描述

MyBatis 是基于 JDBC 的

4. 添加 Service 层代码

import com.example.demo.mapper.UserMapper;
import com.example.demo.model.UserInfo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class UserService {

    @Resource
    private UserMapper userMapper;

    public UserInfo getUserById(Integer id) {
        return userMapper.getUserById(id);
    }

}

5. 添加 Controller 层代码

import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/getuserbyid")
    public UserInfo getUserById(Integer id){
        if(id == null) return null;
        return userService.getUserById(id);
    }
}

在这里插入图片描述

2.5 测试数据

在这里插入图片描述

2.6 添加插件 MyBatisX

左侧出现的小鸟是我添加的插件,点击小鸟他会自动帮我们找到对应的方法,非常的方便,可查
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.7 添加日志文件

我们可以添加日志文件以便于我们操作之后排查错误

# 开启 MyBatis SQL 打印
logging:
  level:
    com:
      example:
        demo: debug
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

在这里插入图片描述
在这里插入图片描述

3. MyBatis 增删改查

3.1 增添操作

1. 在 mapper (interface) 添加增添方法声明

//添加用户,返回受影响的行数
    public int add(UserInfo userInfo);

2. 在 xml 中添加 < insert >标签和增添 sql 编写

<!-- 添加用户,返回受影响的行数 -->
    <insert id="add">
        insert into userinfo(username,password,photo) values(#{username},#{password},#{photo})
    </insert>

在这里插入图片描述

3. service 层

public int add(UserInfo userInfo){
        return userMapper.add(userInfo);
    }

4. controller 层

@RequestMapping("/add")
    public int add(UserInfo userInfo){
        userInfo.setUsername("张三");
        userInfo.setPassword("123");
        userInfo.setPhoto("default.png");
        return userService.add(userInfo);
    }

5. 测试
在这里插入图片描述在这里插入图片描述

3.2 删除操作

1. 在 mapper(interface) 里面添加删除的代码声明

 // 删除方法
    public int del(@Param("id") Integer id);

2. 在 xml 中添加 < delete >标签和删除 sql 编写

<!-- 根据用户 id 删除用户 -->
    <delete id="del">
        delete from userinfo where id=#{id}
    </delete>

在这里插入图片描述

3. service 层

 public int del(Integer id){
        return userMapper.del(id);
    }

4. controller 层

 @RequestMapping("/del")
    public int del(Integer id){
        return userService.del(id);
    }

5. 测试
在这里插入图片描述
在这里插入图片描述

3.3 修改操作

1. 在 mapper(interface) 里面添加修改的代码声明

// 修改方法【根据id修改名称】
    public int update(@Param("id") Integer id,
                      @Param("username") String username);

2. 在 xml 中添加 < update >标签和修改 sql 编写

 <!-- 根据用户 id 修改用户名称 -->
    <update id="update">
        update userinfo set username=#{username} where id=#{id}
    </update>

3. service 层

public int update(Integer id,String username){
        return userMapper.update(id,username);
    }

4. controller 层

@RequestMapping("/update")
    public int update(Integer id,String username){
        return userService.update(id,username);
    }

5. 测试
在这里插入图片描述在这里插入图片描述

3.4 查找操作

1. 在 mapper(interface) 里面添加查找的代码声明

// 根据用户名来查询用户
    public UserInfo getUserByUsername(@Param("username") String username);

一般是根据 id 来查找,因为用户名也可能重复

2. 在 xml 中添加 < select >标签和查找 sql 编写

<!-- 根据用户名查询用户 -->
    <select id="getUserByUsername" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username=#{username}
    </select>

3. service 层

public UserInfo getUserByUsername(String username){
        return userMapper.getUserByUsername(username);
    }

4. controller 层

@RequestMapping("/getuserbyusername")
    public UserInfo getUserById(String username){
        if(username == null) return null;
        return userService.getUserByUsername(username);
    }

5. 测试
在这里插入图片描述

3.5 汇总

1. controller 层
在这里插入图片描述
2. mapper 层
在这里插入图片描述

3. model 层
在这里插入图片描述

4. service 层
在这里插入图片描述

5. XML 文件
在这里插入图片描述

我们发现了执行这些操作以后他是会"污染"我们的数据库的,那么如果我们只是想单纯的测试代码的正确性,这个时候就可以使用SpringBoot单元测试

4. SpringBoot单元测试

4.1 单元测试优点

  1. 可以非常简单,直观,快速的测试某一个功能是否正确
  2. 使用单元测试可以帮我们在打包的时候,发现一些问题,因为在打包之前,所有的单元测试必须通过,否则不能打包成功
  3. 使用单元测试,在测试功能的时候,可以不污染连接的数据库,也就是可以不对数据库进行任何改变的情况下,进行测试功能

4.2 单元测试的实现

4.2.1 准备工作: 确认项目中已经内置了测试框架

在这里插入图片描述

4.2.2 生成单元测试的类

在 mapper 包下:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

4.2.3 配置单元测试的类添加 @SpringBootTest 注解,添加单元测试的业务代码

1. 添加注解
在这里插入图片描述

2.添加单元测试的业务代码

在这里插入图片描述
在这里插入图片描述

4.3 简单断言说明

在这里插入图片描述

断⾔:如果断⾔失败,则后⾯的代码都不会执⾏。

4.4 添加 @Transactional 注解执行回滚事务

我现在的数据库
在这里插入图片描述

执行修改操作:
在这里插入图片描述

修改成功:
在这里插入图片描述

在观察原数据库并没发生改变:
在这里插入图片描述

执行删除操作:
在这里插入图片描述

删除成功:
在这里插入图片描述

观察原数据库也没发生改变:
在这里插入图片描述

相关代码:

import com.example.demo.model.UserInfo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
class UserMapperTest {

    @Resource
    private UserMapper userMapper;

    @Test
    void getUserById() {
        UserInfo userInfo = userMapper.getUserById(1);
        System.out.println(userInfo);
    }

    // 在单元测试中添加此注解,表示在方法执行完之后回滚事务
    @Transactional
    @Test
    void update() {
        int result = userMapper.update(2, "张三");
        Assertions.assertEquals(1, result);
    }

    @Transactional
    @Test
    void del() {
        int result = userMapper.del(2);
        System.out.println("受影响的行数:" + result);
        Assertions.assertEquals(1, result);
    }

    @Transactional
    @Test
    void add() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("王五");
        userInfo.setPassword("123");
        userInfo.setPhoto("default.png");
        int result = userMapper.add(userInfo);
        System.out.println("添加的结果:" + result);
        Assertions.assertEquals(1, result);
    }
}

4.5 返回自增 id

我们不仅想看到受影响的行数,还想看到修改后的 id

1. mapper层接口:

// 添加用户,返回受影响的行数和自增 id
    public int addGetId(UserInfo userInfo);

2. XML 文件:

 <!-- 添加用户,返回受影响的行数和自增 id -->
    <insert id="addGetId" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
        insert into userinfo(username,password,photo) values(#{username},#{password},#{photo})
    </insert>

useGeneratedKeys:这会令 MyBatis 使⽤ JDBC 的 getGeneratedKeys ⽅法来取出由数据库内部⽣成的主键(⽐如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的⾃动递增字段),默认值:false。
keyColumn:设置⽣成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第⼀列的时候,是必须设置的。如果⽣成列不⽌⼀个,可以⽤逗号分隔多个属性名称。
keyProperty:指定能够唯⼀识别对象的属性,MyBatis 会使⽤ getGeneratedKeys 的返回值或 insert 语句的 selectKey ⼦元素设置它的值,默认值:未设置(unset)。如果⽣成列不⽌⼀个,可以⽤逗号分隔多个属性名称

3. 单元测试代码:

//    @Transactional
    @Test
    void addGetId() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("老六");
        userInfo.setPassword("123");
        userInfo.setPhoto("default.png");
        System.out.println("添加之前的 user id: "+userInfo.getId());
        int result = userMapper.addGetId(userInfo);
        System.out.println("受影响的行数: "+result);
        System.out.println("添加之后的 user id: "+userInfo.getId());
        Assertions.assertEquals(1,result);
    }

注释掉了回滚:
在这里插入图片描述
在这里插入图片描述

4.6 一些查询操作

4.6.1 ${} 和 #{} 的区别演示

① 根据 id 查找用户

先看 #{} 操作根据 id 查找用户

在这里插入图片描述在这里插入图片描述在这里插入图片描述

执行的 JDBC 代码:(针对 int 类型的参数)
在这里插入图片描述

接下来${},其他代码不变
在这里插入图片描述
执行的 JDBC 代码:(针对 int 类型)
在这里插入图片描述

前者体现的预处理(预查询),后者体现的即时查询

② 根据用户名查找用户

我们在看看针对 String 类型参数:
先使用 #{} 根据用户名查找 用户
在这里插入图片描述在这里插入图片描述在这里插入图片描述

执行的 JDBC 代码:(针对 String 类型)

在这里插入图片描述

接下来${},其他代码不变

在这里插入图片描述
执行的 JDBC 代码:(针对 String 类型)
在这里插入图片描述

报错了,他的sql语句相当于是:
在这里插入图片描述

并没有加引号

③ 排序功能

像一些商品基本都要有这个排序功能(按价格从高到低,从低到高)我这里就按 id 来排序

先看 #{}
在这里插入图片描述在这里插入图片描述
报错了:
在这里插入图片描述
他的 sql 相当于:
在这里插入图片描述

再看 ${}
在这里插入图片描述
在这里插入图片描述

当传递的是一个 SQL 关键字(SQL 命令)的时候,只能使用 ${},此时如果使用 #{} 就会认为传递的一个普通的值,而非 SQL 命令,所以执行就会报错
注意 ${} 会有 SQL 注入问题,我们不得不使用 ${} 时,那么一定要在业务代码中,对传递的值进行安全验证

④ SQL 注入演示(${})

假设我们有一个登录功能:
先看 #{}
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

再看 ${}

在这里插入图片描述
在这里插入图片描述

他的 SQL 是这样的(已经恒等了):

在这里插入图片描述

⑤ 特殊查询: like 查询

根据名称进行模糊查询
先看 #{}
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

报错了:
在这里插入图片描述

他对应的 SQL:
在这里插入图片描述

这里他是不能直接使用 ${}.可以使用mysql内置函数 concat() 来处理:
在这里插入图片描述在这里插入图片描述

4.6.2 总结区别

  1. 定义不同: #{} 预处理,而 ${} 是直接替换
  2. 使用不同: #{} 适用于所有类型的参数匹配,但 ${} 只适用于数值类型
  3. 安全性不同: #{} 性能高,并且没有安全问题: 但 ${} 存在 SQL 注入的安全问题

5. resultType VS resultMap

在 resultType中,如果我们在实体类中的字段和mysql中的字段不匹配
在这里插入图片描述
这样我们是查不到 对应的值的,这时候我们就可以使用 resultMap 来手动进行映射的处理

 <resultMap id="BaseMap" type="com.example.demo.model.UserInfo">
        <!-- 主键映射 -->
        <id column="id" property="id"></id>
        <!-- 普通属性映射 -->
        <result column="username" property="name"></result>
    </resultMap>
    
    <!-- 根据用户 id 查询用户 -->
    <select id="getUserById" resultMap="BaseMap">
        select * from userinfo where id=#{id}
    </select>

在这里插入图片描述

6. 多表查询

6.1 一对一查询

⼀对⼀映射要使⽤ <association> 标签,具体实现如下(⼀篇⽂章只对应⼀个作者):

我们在建一个文章实体类:
在这里插入图片描述

1. model层:

import lombok.Data;

@Data
public class ArticleInfo {
    private int id;
    private String title;
    private String content;
    private String createtime;
    private String updatetime;
    private int uid;
    private int rcount;
    private int state;
    private UserInfo userInfo;
}

多加了一个 UserInfo 类

2. mapper层:

import com.example.demo.model.ArticleInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface ArticleMapper {
    //根据文章 id 获取文章
    public ArticleInfo getArticleById(@Param("id") Integer id);
}

3. 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">
<!-- namespace 要设置是实现接口的具体包名加类名 -->
<mapper namespace="com.example.demo.mapper.ArticleMapper">

    <resultMap id="BaseMap" type="com.example.demo.model.ArticleInfo">
        <id column="id" property="id"></id>
        <result column="title" property="title"></result>
        <result column="content" property="content"></result>
        <result column="createtime" property="createtime"></result>
        <result column="updatetime" property="updatetime"></result>
        <result column="uid" property="uid"></result>
        <result column="rcount" property="rcount"></result>
        <result column="state" property="state"></result>
        <association property="userInfo"
                     resultMap="com.example.demo.mapper.UserMapper.BaseMap"
                     columnPrefix="u_"></association>
    </resultMap>
    <select id="getArticleById" resultMap="BaseMap">
        select a.*,u.id u_id,u.username u_username,u.password u_password from articleinfo a left join userinfo u on
            a.uid=u.id where a.id=#{id}
    </select>
</mapper>

4. 单元测试代码:
在这里插入图片描述
在这里插入图片描述

@Slf4j 打印:
在这里插入图片描述

以上使⽤ <association>标签,表示⼀对⼀的结果映射:
property 属性:指定 Article 中对应的属性,即⽤户。
resultMap 属性:指定关联的结果集映射,将基于该映射配置来组织⽤户数据。
columnPrefix 属性:绑定⼀对⼀对象时,是通过columnPrefix+association.resultMap.column 来映射结果集字段。
association.resultMap.column是指 标签中 resultMap属性,对应的结果集映射中,column字段。
注意事项:column不能省略
在这里插入图片描述

6.2 一对多实现

跟一对一差不多,⼀对多需要使⽤ <collection> 标签,⽤法和 <association> 相同,

1. model层:

import lombok.Data;

import java.util.List;

/**
 * 用户实体类
 */
@Data
public class UserInfo {
    private Integer id;
    private String name;
    private String password;
    private String photo;
    private String createtime;
    private String updatetime;
    private int state;
    private List<ArticleInfo> artlist;
}

2. mapper层:

 // 查询用户及用户发表的所有文章,根据用户id
    public UserInfo getUserAndArticleByUid(@Param("uid") Integer uid);

3. XML层:

<mapper namespace="com.example.demo.mapper.UserMapper">
    <resultMap id="BaseMap" type="com.example.demo.model.UserInfo">
        <!-- 主键映射 -->
        <id column="id" property="id"></id>
        <!-- 普通属性映射 -->
        <result column="username" property="name"></result>
        <result column="password" property="password"></result>
        <result column="photo" property="photo"></result>
        <result column="createtime" property="createtime"></result>
        <result column="updatetime" property="updatetime"></result>
        <result column="state" property="state"></result>
        <collection property="artlist"
                    resultMap="com.example.demo.mapper.ArticleMapper.BaseMap"
                    columnPrefix="a_">
        </collection>
    </resultMap>

    <select id="getUserAndArticleByUid" resultMap="BaseMap">
        select u.*,a.id a_id,a.title a_title,a.content a_content,
               a.createtime a_createtime,
               a.updatetime a_updatetime from userinfo u left join articleinfo a
                                                                   on u.id=a.uid where u.id=#{uid}
    </select>

4. 单元测试代码:
在这里插入图片描述在这里插入图片描述在这里插入图片描述

7. 动态 SQL

7.1 if 标签

判断一个参数是否有值的,如果没值,那么就会隐藏 if 中 的 SQL
就像我们在填写一些注册信息的时候,有些项可以填也可以不填,有些就是必须要填.

简单语法:
在这里插入图片描述

举例:添加用户

1. mapper层:

// 添加用户,添加用户时 photo是非必传参数
    public int add2(UserInfo userInfo);

2. XML:

 <!-- 添加用户,添加用户时 photo是非必传参数 -->
    <insert id="add2">
        insert into userinfo(username,password
        <if test="photo!=null">
            ,photo
        </if>
        ) values(#{name},#{password}
        <if test="photo!=null">
            ,#{photo}
        </if>
        )
    </insert>

3. 不加 photo 的测试代码:
在这里插入图片描述在这里插入图片描述

4. 传值 photo 时:

在这里插入图片描述在这里插入图片描述

对应数据库值:
在这里插入图片描述

7.2 trim 标签

最主要的作用就是 去除 SQL 语句前后多余的某个字符,向我们经常会在最后添加的值多加一个逗号啥的

主要语法:
在这里插入图片描述

1. mapper层:

// 添加用户,其中 username、password、photo 都是非必传参数,
    // 但至少会传递一个参数
    public int add3(UserInfo userInfo);

2. XML层:

<insert id="add3">
        insert into userinfo
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="name!=null">
                username,
            </if>
            <if test="password!=null">
                password,
            </if>
            <if test="photo!=null">
                photo
            </if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="name!=null">
                #{name},
            </if>
            <if test="password!=null">
                #{password},
            </if>
            <if test="photo!=null">
                #{photo}
            </if>
        </trim>
    </insert>

3. 单元测试代码:
在这里插入图片描述
在这里插入图片描述

7.3 where 标签

主要作用就是实现查询中的 where sql 替换的,他可以实现如果没有任何的查询条件,那么他可以因此查询中的 where sql,但是如果存在查询条件,那么会生成 where 的 sql 查询,并且使用 where 标签可以自动的去除最前面一个 and 字符

举例:根据 id 查找用户

1. mapper层:

// 根据用户 id 查询用户
    public UserInfo getUserById(@Param("id") Integer id);

注意:这里只返回一个,我就把数据库保留了一份
在这里插入图片描述

2. XML层:

<!-- 根据 id 查询用户 -->
    <select id="getUserById" resultMap="BaseMap">
        select * from userinfo
        <where>
            <if test="id!=null">
                id=#{id}
            </if>
        </where>
    </select>

3. 单元测试代码:
在这里插入图片描述
在这里插入图片描述

4. 加上 and:
在这里插入图片描述

测试代码:
在这里插入图片描述
在这里插入图片描述

注意: and 在前面不能在后面
在这里插入图片描述
在这里插入图片描述

7.4 set 标签

主要作用就是在进行修改操作时,配合 if 来处理非必传输的,它的特点就是会自动去除最后一个英文逗号

举例,修改数据:在这里插入图片描述

1. mapper层:

int update2(UserInfo userInfo);

2. XML层:

<update id="update2">
        update userinfo
        <set>
            <if test="name!=null">
                username=#{name},
            </if>
            <if test="password!=null">
                password=#{password},
            </if>
            <if test="photo!=null">
                photo=#{photo}
            </if>
        </set>
        where id=#{id}
    </update>

3. 测试代码:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

7.5 foreach 标签

作用主要就是对集合进行循环的

<foreach>标签有如下属性:
collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象
item:遍历时的每⼀个对象
open:语句块开头的字符串
close:语句块结束的字符串
separator:每次遍历之间间隔的字符串

举例:根据多个用户 id 删除用户:

1. mapper层:

int delIds(List<Integer> ids);

2. XML层:

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

方便观察,我们可以加几条数据:
在这里插入图片描述
3. 单元测试代码:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

粉色的志明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值