Mybatis 查询数据库

  • 1. MyBatis 是什么?
  • 2. 创建 MyBatis 项目
    • 2.1 准备工作,创建数据库和数据表
    • 2.2 添加 MyBatis 相关依赖
    • 2.3 配置数据库连接字符串 和 MyBatis(保存的 XML 的目录)
      • 2.3.1 配置数据库的连接信息
      • 2.3.2 配置 MyBatis 的 XML 保存路径
    • 2.4 使用 MyBatis 的操作模式操作数据库
      • 2.4.1 添加代码
    • 2.5 测试数据
    • 2.6 添加插件 MyBatisX
    • 2.7 添加日志文件
  • 3. MyBatis 增删改查
    • 3.1 增添操作
    • 3.2 删除操作
    • 3.3 修改操作
    • 3.4 查找操作
    • 3.5 汇总
  • 4. SpringBoot单元测试
    • 4.1 单元测试优点
    • 4.2 单元测试的实现
      • 4.2.1 准备工作: 确认项目中已经内置了测试框架
      • 4.2.2 生成单元测试的类
      • 4.2.3 配置单元测试的类添加 @SpringBootTest 注解,添加单元测试的业务代码
    • 4.3 简单断言说明
    • 4.4 添加 @Transactional 注解执行回滚事务
    • 4.5 返回自增 id
    • 4.6 一些查询操作
      • 4.6.1 ${} 和 #{} 的区别演示
        • ① 根据 id 查找用户
        • ② 根据用户名查找用户
        • ③ 排序功能
        • ④ SQL 注入演示(${})
        • ⑤ 特殊查询: like 查询
      • 4.6.2 总结区别
  • 5. resultType VS resultMap
  • 6. 多表查询
    • 6.1 一对一查询
    • 6.2 一对多实现
  • 7. 动态 SQL
    • 7.1 if 标签
    • 7.2 trim 标签
    • 7.3 where 标签
    • 7.4 set 标签
    • 7.5 foreach 标签

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()
Mybatis 查询数据库_第1张图片

2.2 添加 MyBatis 相关依赖

Mybatis 查询数据库_第2张图片

添加完后不要急着启动项目测试:
Mybatis 查询数据库_第3张图片

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

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

2.3.1 配置数据库的连接信息

这里一般我们会用多个配置文件,以便之后在多个平台运行(最少一般都会有两个)
Mybatis 查询数据库_第4张图片

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

# 配置数据库连接
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

Mybatis 查询数据库_第5张图片

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

我们可以先看一下 MyBatis 整体流程:
Mybatis 查询数据库_第6张图片Mybatis 查询数据库_第7张图片

2.4.1 添加代码

提前创好对应的包:
Mybatis 查询数据库_第8张图片

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 实现上面的接口
固定的格式,自己也可以先保存在能经常拿到的地方:


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 查询数据库_第9张图片

MyBatis 执行过程:
Mybatis 查询数据库_第10张图片

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);
    }
}

Mybatis 查询数据库_第11张图片

2.5 测试数据

Mybatis 查询数据库_第12张图片

2.6 添加插件 MyBatisX

左侧出现的小鸟是我添加的插件,点击小鸟他会自动帮我们找到对应的方法,非常的方便,可查
Mybatis 查询数据库_第13张图片
Mybatis 查询数据库_第14张图片
Mybatis 查询数据库_第15张图片

2.7 添加日志文件

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

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

Mybatis 查询数据库_第16张图片
Mybatis 查询数据库_第17张图片

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>

Mybatis 查询数据库_第18张图片

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. 测试
Mybatis 查询数据库_第19张图片Mybatis 查询数据库_第20张图片

3.2 删除操作

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

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

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


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

Mybatis 查询数据库_第21张图片

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. 测试
Mybatis 查询数据库_第22张图片
Mybatis 查询数据库_第23张图片

3.3 修改操作

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

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

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

 
    <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. 测试
Mybatis 查询数据库_第24张图片Mybatis 查询数据库_第25张图片

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. 测试
Mybatis 查询数据库_第26张图片

3.5 汇总

1. controller 层

2. mapper 层
Mybatis 查询数据库_第27张图片

3. model 层
Mybatis 查询数据库_第28张图片

4. service 层
Mybatis 查询数据库_第29张图片

5. XML 文件
Mybatis 查询数据库_第30张图片

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

4. SpringBoot单元测试

4.1 单元测试优点

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

4.2 单元测试的实现

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

Mybatis 查询数据库_第31张图片

4.2.2 生成单元测试的类

在 mapper 包下:
Mybatis 查询数据库_第32张图片Mybatis 查询数据库_第33张图片
Mybatis 查询数据库_第34张图片Mybatis 查询数据库_第35张图片
Mybatis 查询数据库_第36张图片

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

1. 添加注解
Mybatis 查询数据库_第37张图片

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

Mybatis 查询数据库_第38张图片
Mybatis 查询数据库_第39张图片

4.3 简单断言说明

Mybatis 查询数据库_第40张图片

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

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

我现在的数据库
Mybatis 查询数据库_第41张图片

执行修改操作:
Mybatis 查询数据库_第42张图片

修改成功:
Mybatis 查询数据库_第43张图片

在观察原数据库并没发生改变:
Mybatis 查询数据库_第44张图片

执行删除操作:
Mybatis 查询数据库_第45张图片

删除成功:
Mybatis 查询数据库_第46张图片

观察原数据库也没发生改变:
Mybatis 查询数据库_第47张图片

相关代码:

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 文件:

 
    <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);
    }

注释掉了回滚:
Mybatis 查询数据库_第48张图片
Mybatis 查询数据库_第49张图片

4.6 一些查询操作

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

① 根据 id 查找用户

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

在这里插入图片描述Mybatis 查询数据库_第50张图片Mybatis 查询数据库_第51张图片

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

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

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

② 根据用户名查找用户

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

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

在这里插入图片描述

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

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

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

并没有加引号

③ 排序功能

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

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

再看 ${}
在这里插入图片描述
Mybatis 查询数据库_第53张图片

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

④ SQL 注入演示(${})

假设我们有一个登录功能:
先看 #{}
在这里插入图片描述
在这里插入图片描述
Mybatis 查询数据库_第54张图片
在这里插入图片描述

再看 ${}

在这里插入图片描述
Mybatis 查询数据库_第55张图片

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

Mybatis 查询数据库_第56张图片

⑤ 特殊查询: like 查询

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

Mybatis 查询数据库_第57张图片

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

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

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

4.6.2 总结区别

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

5. resultType VS resultMap

在 resultType中,如果我们在实体类中的字段和mysql中的字段不匹配
Mybatis 查询数据库_第58张图片
这样我们是查不到 对应的值的,这时候我们就可以使用 resultMap 来手动进行映射的处理

 <resultMap id="BaseMap" type="com.example.demo.model.UserInfo">
        
        <id column="id" property="id">id>
        
        <result column="username" property="name">result>
    resultMap>
    
    
    <select id="getUserById" resultMap="BaseMap">
        select * from userinfo where id=#{id}
    select>

Mybatis 查询数据库_第59张图片

6. 多表查询

6.1 一对一查询

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

我们在建一个文章实体类:
Mybatis 查询数据库_第60张图片

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层:


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<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. 单元测试代码:
Mybatis 查询数据库_第61张图片
在这里插入图片描述

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

以上使⽤ 标签,表示⼀对⼀的结果映射:
property 属性:指定 Article 中对应的属性,即⽤户。
resultMap 属性:指定关联的结果集映射,将基于该映射配置来组织⽤户数据。
columnPrefix 属性:绑定⼀对⼀对象时,是通过columnPrefix+association.resultMap.column 来映射结果集字段。
association.resultMap.column是指 标签中 resultMap属性,对应的结果集映射中,column字段。
注意事项:column不能省略
Mybatis 查询数据库_第62张图片

6.2 一对多实现

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

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. 单元测试代码:
Mybatis 查询数据库_第63张图片在这里插入图片描述在这里插入图片描述

7. 动态 SQL

7.1 if 标签

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

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

举例:添加用户

1. mapper层:

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

2. XML:

 
    <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 的测试代码:
Mybatis 查询数据库_第64张图片在这里插入图片描述

4. 传值 photo 时:

Mybatis 查询数据库_第65张图片在这里插入图片描述

对应数据库值:
Mybatis 查询数据库_第66张图片

7.2 trim 标签

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

主要语法:
Mybatis 查询数据库_第67张图片

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. 单元测试代码:
Mybatis 查询数据库_第68张图片
在这里插入图片描述

7.3 where 标签

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

举例:根据 id 查找用户

1. mapper层:

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

注意:这里只返回一个,我就把数据库保留了一份
Mybatis 查询数据库_第69张图片

2. XML层:


    <select id="getUserById" resultMap="BaseMap">
        select * from userinfo
        <where>
            <if test="id!=null">
                id=#{id}
            if>
        where>
    select>

3. 单元测试代码:
Mybatis 查询数据库_第70张图片
在这里插入图片描述

4. 加上 and:
Mybatis 查询数据库_第71张图片

测试代码:
Mybatis 查询数据库_第72张图片
Mybatis 查询数据库_第73张图片

注意: and 在前面不能在后面
Mybatis 查询数据库_第74张图片
Mybatis 查询数据库_第75张图片

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. 测试代码:
Mybatis 查询数据库_第76张图片

在这里插入图片描述

Mybatis 查询数据库_第77张图片

Mybatis 查询数据库_第78张图片

在这里插入图片描述

在这里插入图片描述

7.5 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>

方便观察,我们可以加几条数据:
Mybatis 查询数据库_第79张图片
3. 单元测试代码:
Mybatis 查询数据库_第80张图片

在这里插入图片描述

在这里插入图片描述

你可能感兴趣的:(JavaEE,mybatis,数据库,java,mysql,spring,boot)