• 【MyBatis】MyBatis基础内容介绍


    介绍

    MyBatis是一个框架,是程序和真正的数据库之间的桥梁,MyBatis是居于ORM框架,ORM是object Relational Mapping 对象关系映射

    也就是说,MyBatis是和程序中的类相对应的
    类就是MyBatis中的表
    一个对象就是MyBatis中的一条记录(一行)
    属性就是MyBatis中的字段

    所以我们操作java中的对象的时候,同时也在操作MyBatis中的数据

    搭建MyBatis框架

    1. 添加依赖

    第一步就是添加依赖,**同时要添加MyBatis和Mysql的依赖,**因为MyBatis只是一个框架,一个平台,真正底层实现的还是Mysql

    如果是新创建项目,直接添加就可以了
    如果是老项目,使用EditStarter就可以添加上面两个依赖

    在这里插入图片描述

    2.配置MYSQL连接和MyBatis连接

    虽然我们添加了两个依赖,一个是MySQL,一个是MyBatis,但是我们还没有进行连接.

    MySQL连接:

    在application-dev.yml中设置连接

    spring:  
      datasource:  
        url: jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false  
        username: root  
        password: 1234  
        driver-class-name: com.mysql.cj.jdbc.Driver
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    driver-class-name 如果是5.x以后的才可以设置为com.mysql.cj.jdnc.Driver

    MyBatis配置:

    1. 现在resource文件夹下面创建一个文件夹,之后这个里面存放的都是mybatis的文件
      在这里插入图片描述

    2. 然后在主配置文件中设置一下mybatis的配置路径

    # application.yml:
    # 配置mybatis的保存路径  
    mybatis:  
      mapper-locations: classpath:mybatis/**Mapper.xml
    
    • 1
    • 2
    • 3
    • 4

    3.创建数据库表

    -- 创建数据库
    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

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

    4.创建实体类

    创建一个Model包,里面创建一个UserInfo类
    这个类里面的属性和我们之前创建的表中的属性相同

    package com.example.demo.Model;  
      
    import lombok.Data;  
      
    @Data  
    public class UserInfo {  
        private int id;  
        private String username;  
         private String    password ;  
         private  String photo ;  
         private  String createtime ;  
         private String updatetime;  
         private int state;  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    5.MyBatis框架

    要使用MyBatis框架的话,主要有一下两个操作,一个是有接口方法,一个是使用.xml的接口方法的实现.

    只有这两个同时使用才可以完成对数据库的操作

    1.创建Mapper

    创建一个Mapper包,里面放的都是和上面实体类对应的接口类
    每一个接口类中都是一个个方法,但是这个只是一个声明,声明这个动作.真正的实现要到.xml中使用sql实现

    要记住加上啊Mapper注解

    @Mapper  
    public interface userMapper {  
                                //可以视为传递给数据库的名字  
        public UserInfo getUserById(@Param("id") Integer id);  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.xml中的SQL

    1. Mapper标签里面的namespace里面写的是具体是哪一个Mapper里面的接口
    2. select标签的id方法指的是方法名
    3. select标签中的resultType是返回的类名
    4. sql中的id值要使用${}进行读取
      
    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">  
      
        <select id="getUserById" resultType="com.example.demo.Model.UserInfo">  
      
            select * from userinfo where id=${id}  
        select>  
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.MyBatis的SQL打印

    打印真正的SQL语句,在application-dev.yml中进行配置

    1. 先设置日志级别为debug类型的
    2. 然后再配置mybatis的信息
    # 开启 MyBatis SQL 打印
    # 要先将这个日志级别设置好为debug类型的
    logging:
      level:
        com:
          example:
            demo: debug
    mybatis:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    配置完成之后我们就可以看到控制台上面的完整的SQL语句

    ==>  Preparing: select * from userinfo where id=1
    ==> Parameters: 
    <==    Columns: id, username, password, photo, createtime, updatetime, state
    <==        Row: 1, admin, admin, , 2021-12-06 17:10:48, 2021-12-06 17:10:48, 1
    <==      Total: 1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    单元测试

    上面我们完成了Mybatis的编写,但是还需要Service层,Controller层,打开浏览器发送请求,这样的测试过程是麻烦的

    所以为了方便我们进行验证,我们就可以使用单元测试进行模拟一下

    1. 优点

    1. 可以方便,快捷的测试一个代码块是否合理
    2. 在进行打包之前会进行单元测试,如果单元测试不通过,就不会打包成功,这样就可以及时的发现错误
    3. 在测试的时候不会对数据库的造成污染

    2.使用

    1. 包含测试框架

    在我们创建SpringBoot的时候,就已经内置了这个测试框架了,这个框架底层是通过JUnit实现的

    <dependency>  
       <groupId>org.springframework.bootgroupId>  
       <artifactId>spring-boot-starter-testartifactId>  
       <scope>testscope>  
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.生成单元测试的类

    哪一个类都可以生成关于它的单元测试的类,只要有了框架,我们就可以对一个类进行测试.

    1. 在要测试的类右键generate
    2. 选择test选项
    3. 配置测试类的信息
      在这里插入图片描述

    配置完成之后,我们就会发现,idea就会在test的文件夹下面生成我们刚才配置的类.
    注意是在test绿色文件夹下面生成的:
    在这里插入图片描述

    3.配置测试类

    1.给单元测试类添加注解@SpringBootTest表示当前单元测试运行在SpringBoot的环境中
    2. 编写测试代码

    package com.example.demo.Mapper;  
      
    import com.example.demo.Model.UserInfo;  
    import org.junit.jupiter.api.Test;  
    import org.springframework.boot.test.context.SpringBootTest;  
      
    import javax.annotation.Resource;  
      
    import static org.junit.jupiter.api.Assertions.*;  
      
    @SpringBootTest  
    class UserMapperTest {  
      
        @Resource  
        UserMapper userMapper;  
      
        @Test  
        void getUserById() {  
            UserInfo userInfo=userMapper.getUserById(1);  
            System.out.println(userInfo);  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    4.测试方法

    直接使用方法旁边的Run按钮就可以直接对这一个方法进行测试了

    UserInfo(id=1, username=admin, password=admin, photo=, createtime=2021-12-06 17:10:48, updatetime=2021-12-06 17:10:48, state=1)
    
    • 1

    5.断言

    判断我们的测试结果是否成功
    ![[Pasted image 20220727135738.png]]

      
    @Test  
    void getUserById() {  
        UserInfo userInfo=userMapper.getUserById(2);  
        //断言,测试  
        Assertions.assertNotNull(userInfo);  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    更改数据

    1. 在userMapper中添加一个方法
    //根据用户id更改用户信息  将参数都加上@param注解更加稳妥,不易报错  
    public int updateUserName(@Param("id") Integer id,  
                          @Param("username") String username);
    
    • 1
    • 2
    • 3
    1. 在userMapper.xml中实现这个方法

    这个#里面的名字和上面Param中的字符串对应

    <update id="updateUserName">  
        update userinfo set username=#{username} where id=#{id}  
    update>
    
    • 1
    • 2
    • 3
    1. 进行单元测试
    @Test  
    void updateUserName() {  
        int length=userMapper.updateUserName(1,"lxylxy");  
        Assertions.assertEquals(1,length);  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 最后执行
      执行结果:
    ==>  Preparing: update userinfo set username=? where id=?
    ==> Parameters: lxylxy(String), 1(Integer)
    <==    Updates: 1
    
    • 1
    • 2
    • 3

    成功执行

    删除数据

    1. 在UserMapper中添加删除方法
    //更加用户id删除用户  
    public int deleteUser(@Param("id") Integer id);
    
    • 1
    • 2
    1. 在userMapper.xml中实现方法
    <delete id="deleteUser">  
        delete from userinfo where id=#{id}  
    delete>
    
    • 1
    • 2
    • 3
    1. 单元测试
      这个Transactional在SpringBootTest类,表示在方法执行完之后回滚
      
    @Test  
    @Transactional//加上这个就不会真正的删除,不会污染数据库  
    void deleteUser() {  
        int length=userMapper.deleteUser(1);  
        Assertions.assertEquals(1,length);  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    添加数据

    1. UserMapper的代码
    //添加用户  
    public Integer addUser(UserInfo userInfo);
    
    • 1
    • 2
    1. userMapper.xml中的代码

    这个添加方法的sql有一点难度,还是使用#{},{}直接写对象的属性就可以

      
    <insert id="addUser">  
        insert into userinfo (username,password,photo,state) values  
        (#{username},#{password},#{photo},1)  
    insert>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    下面写一个返回id的版本的添加数据,就是在insert标签上面添加多个属性

    userGenerateKeys为true表示可以为获取到主键
    keyProperties表示要返回的键值的名字

      
    <insert id="addUser2" useGeneratedKeys="true" keyProperty="id" keyColumn="id">  
        insert into userinfo (username,password,photo,state) values  
        (#{username},#{password},#{photo},1)  
    insert>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 测试代码
    @Test  
    void addUser() {  
        int lenght=userMapper.addUser(new UserInfo("12","111",""));  
        Assertions.assertEquals(1,lenght);  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    ${}和#{}的区别

    1. 定义不同:
      #{}是使用模板形式(也叫做预处理模式),就是先有的sql语句,然后再对传入的值进行set如sql中.
      ${}是使用直接替换的方式,直接将sql进行执行
    2. 使用不同
      正是由于它们的定义不同,#{}是提取元素然后注入,${}直接执行的方式,所以,对于字符串类型的元素,${}是没有引号标记的,所以它只可以传递int类型的数据,但是#{}可以传递任意数据
    3. 安全性不同
      因为#{}会进行提取,所以它更加安全,而${}可能会传入各式各样的sql语句,不安全

    传递sql关键字

    但是,当我们传输的内容是一个sql的关键字如desc/asc的时候,我们就要使用${}了,因为它会直接将关键字拿过来,这个时候我们在业务代码那里就要加上验证,防止sql注入的问题
    但是对于#{}来说,它会以为我们传递的是一个value,是一个值,还会给它加上引号’’

    使用${}

    select * from userinfo order by createtime desc
    
    • 1

    使用#{}

    select * from userinfo order by createtime 'desc'
    
    • 1

    使用’${}’

    因为我们之前发现${}只会简单的将数据拷贝,不会加上引号,所以我们可以在它的两边加上’'试试.

    但是这样依旧还是有问题的,如果我们输入的字符串是' or 1='1的话,就会发生错误,原因是:

    select * from userinfo where username='lxylxy' and password='' or 1='1'
    
    • 1

    我们发现最后生成的sql语句竟然是这样的,这样的话就会造成数据泄露了.

    所以,我们最好还是使用#{}
    结果是:

    ==>  Preparing: select * from userinfo where username=? and password=?
    ==> Parameters: lxylxy(String), ' or 1='1(String)
    <==      Total: 0
    
    • 1
    • 2
    • 3

    所以,我们最好还是使用#{}

    like查询

    我们有的时候会进行模糊查询,比如说用户想要查找用户姓名中含有1的用户,这个输入输入1,就要求打印出来.

    这个时候,sql语句我们希望是%1
    我们如果使用#{}来进行like查询的时候.

    select * from userinfo where username like '%#{username}%'
    
    • 1

    最后的结果是:

    select * from userinfo where username like '%'1'%'
    
    • 1

    是达不到要查询的效果的

    所以但是我们使用${}也是不太好的,因为会有sql注入的风险

    所以,这个时候我们可以使用mysql提供的一个方法concat进行字符串之间的拼接,这样就可以消除引号的影响了

    select * from userinfo where username like concat('%',#{username},'%')
    
    • 1

    resultMap

    之前我们进行查询语句的时候,都是使用resultType进行接收的,但是下面有两种时候,我们需要使用resultMap进行接收

    数据库字段和程序属性不同

    当数据库的字段和程序的属性不同的时候,就一定得使用resultMap进行接收了,使用resultType是接收不到的

    1. 先在userMapper.xml的Mapper标签中创建resultMap标签
    # 映射的名字,对应的类的名字
    <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="pwd">result>  
    resultMap>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 在查询标签中,不使用resultType属性了,而是使用resultMap属性

    里面填写的就是上面的resultMap的名字

        <select id="getUserById" resultMap="baseMap">  
      
            select * from userinfo where id=#{id}  
        select>
    
    • 1
    • 2
    • 3
    • 4

    另外,还记得添加元素返回主键的那个sql语句吗.

    我们传入的是这个用户类,传入的是程序中类的类型,所以如果程序中类的名字和属性值不一样的话,这个sql中的名字也要变为和程序中的类的属性相同名

    <insert id="addUser2" useGeneratedKeys="true" keyProperty="id" keyColumn="id">  
        insert into userinfo (username,password,photo,state) values  
        (#{name},#{pwd},#{photo},1)  
    </insert>
    
    • 1
    • 2
    • 3
    • 4

    一对一查询:association

    当单表查询的时候,我们也是要使用到resultMap的

    在ArticleInfo类中,如果我们加入UserInfo属性,这个属性在数据库中没有,但是我们在类中进行添加了

    package com.example.demo.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;  //新加入的属性
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    如果我们想要通过文章的id,获取ArticleInfo的话

    ArticleMapper的方法:

    package com.example.demo.Mapper;  
      
    import com.example.demo.Model.ArticleInfo;  
    import org.apache.ibatis.annotations.Mapper;  
      
    @Mapper  
    public interface ArticleMapper {  
      
        public ArticleInfo getArticleById(Integer id);  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    那么我们在ArticleMapper的xml文件中就要注意了,
    因为我们的ArticleInfo是包含了UserInfo的

    sql语句:

    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 u.id =1
    
    • 1
    • 2

    这个大体上是搜索了ArticleInfo的全部信息和UserInfo的id,username,password
    还给ArticleInfo起别名为a,UserInfo的别名是u

    但是因为是select语句,所以要带有返回值,因为返回值中多了一个UserInfo.所以我们需要新建立一个ResultMap

    1. 这个resultMap的名字是BaseMap,对应的类型是Model里面的ArticleInfo
    2. 里面的内容有id,result,分别是主键属性对应和普通属性对应
    3. 另外还多了一个就是association标签,这个意思是这个和userInfo先关联
    4. association的property标签是程序中的类名,
      resultMap标签是usrInfoMapper.xml里面的关于userInfo的resultMap.这也就表明了在userInfoMapper.xml里面也要有关于userInfo的一对一的标签
      columnPrefix表示为了防止userInfo和ArticleInfo中的属性值一样(因为相同的话就会它们就会被赋为相同值),设置的userInfo的前缀值
    5. 我们在sql语句中的userInfo的任何字段的前面都要加上columnPrefix前缀
    <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="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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    一对多查询:connection

    一个用户对应多篇文章

    这个和一对一十分的相似,只是对应了多篇文章了

    UserInfo类:

    我们注意到最后的属性,List

    @Data  
    @AllArgsConstructor  
    public class UserInfo {  
        private int id;  
        private String name;  
    //     private String    password ;  
    private String    pwd ;  
         private  String photo ;  
         private  String createtime ;  
         private String updatetime;  
         private int state;  
         private List<ArticleInfo> articleInfoList;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    UserMapper.xml:

    对于UserInfo的ResultMap:

    1. resultMap标签的id是这个标签的名字
    2. type对应的是映射到哪一个类,也就是UserInfo类
    3. 里面的id标签对应的是数据库中的主键
    4. 里面的result标签对应的是数据库中每一个正常的非主键,每一个都要进行映射
    5. 表示其他的表使用collection标签,property表示对应的类中的值,resultMap表示一个对应的ArticleInfo的resultMap,columnPrefix为了防止多张表中出现相同的字段名,所以给这个表添加的前缀名
    <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="pwd">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="articleInfoList"  
                    resultMap="com.example.demo.Mapper.ArticleMapper.BaseMap"  
                    columnPrefix="a_"  
                    >  
        collection>  
    resultMap>  
      
    <select id="getUserAndArticleById" 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 a.uid=u.id where u.id=#{id}  
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    动态sql

    if标签

    当某些参数,可传递,可不传递的时候,我们就可以使用if标签来修饰这个属性

    比如说userinfo中的photo属性.如果它是否传递都是可以的
    那么就可以使用if标签进行标记

      
    <!--    添加可以不传入photo的用户信息-->  
        <insert id="addUser3">  
            insert into userinfo (  
            username  
            ,password  
            <if test="photo!=null">  
                ,photo  
            </if>  
            ) values(  
            #{name},#{pwd}  
            <if test="photo!=null">  
                ,#{photo}  
            </if>  
            )  
        </insert>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    使用if标签进行拼接

    trim

    当有多个可以不传入的参数,但是至少有一个会被传入时,我们就可以使用trim和if标签组合起来使用

    trim标签主要用户拼接前后缀和删除指定的前后字符

      
    <!--    使用trim进行拼接和裁剪的-->  
       <insert id="addUser4">  
           insert into userinfo  
           <trim prefix="(" suffix=")" suffixOverrides=",">  
               <if test="name!=null">  
                   username,  
               </if>  
               <if test="pwd!=null">  
                   password,  
               </if>  
               <if test="photo!=null">  
                   photo,  
               </if>  
           </trim>  
           values  
           <trim prefix="(" suffix=")" suffixOverrides=",">  
               <if test="name!=null">  
                   #{name},  
               </if>  
               <if test="pwd!=null">  
                   #{pwd},  
               </if>  
               <if test="photo!=null">  
                   #{photo},  
               </if>  
           </trim>  
       </insert>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    where

    当使用where查询时,查询的条件是不确定的,有的参数可能传入,有的参数可能不传入.也就是不确定的条件下

    我们就可以使用where标签来代替常规的where sql语句

    主要作用:

    1. 和if标签配合,拼接不为null的字段
    2. 自动取出每一条语句的最前方的and连接符
      
    <select id="getUserByNameAndPwd" resultMap="baseMap">  
        select * from userinfo  
        <where>  
            <if test="name!=null">  
                and username=#{name}  
            </if>  
            <if test="pwd!=null">  
                and password=#{pwd}  
            </if>  
        </where>  
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    当不传入name属性时:
    会不拼接name,只拼接password,而且还会去掉password前面的and

    select * from userinfo WHERE password=?
    
    • 1

    where相当于trim的prefix是where,prefixoverride是and

    set

    用于修改字段的值
    update userinfo set username =‘xxx’ where id=1;

    这个动态的set就是为了解决传入的内容不确定的问题的

    <update id="updateUserInfo">  
        update userinfo  
        <set>  
            <if test="name!=null">  
                username=#{name},  
            </if>  
            <if test="pwd!=null">  
                password=#{pwd},  
            </if>  
        </set>  
        where id=#{id}  
    </update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    当我们只传入了name的时候sql语句是这样的:

    update userinfo SET username=? where id=?
    
    • 1

    相当于trim的prefix=set,suffixoverrides=‘,’

    foreach标签

    当要删除多个值的时候,就可以使用foreach来进行遍历

    foreach标签的常用属性

    1. collection 表示集合的名字
    2. item 表示每一个集合中的对象
    3. open 表示开头的字符串
    4. close 表示结尾的字符串
    5. separator 表示分隔的字符串
      
    <delete id="deleteListUser">  
        delete from userinfo where id in  
        <foreach collection="list" open="(" close=")" item="id" separator=",">  
            #{id}  //要和item里面的对应
        </foreach>  
    </delete>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    Preparing: delete from userinfo where id in ( ? , ? , ? )
    ==> Parameters: 15(Integer), 18(Integer), 17(Integer)
    
    • 1
    • 2
  • 相关阅读:
    第一个微信小程序的诞生
    KMP算法
    普元EOS学习笔记-EOS8.3精简版安装
    netty系列之:kequeue传输协议详解
    秋招项目总结
    OpenHarmony应用开发入门教程(一、开篇)
    Java开发学习(八)----IOC/DI配置管理第三方bean、加载properties文件
    Linux电话本的编写-shell脚本编写
    android隐藏输入法的一些尝试,最后一个可行
    Python基础入门例程8-NP8 为整数增加小数点
  • 原文地址:https://blog.csdn.net/weixin_51574797/article/details/126088775