1.动态SQL的作用?

1.1 动态SQL的作用

当我们注册时需要填写一些信息,有写信息必须填写,有些信息可以不填写,这时我们使用传统的SQL无法满足需求,需要使用动态SQL。

比如,注册时让填写 用户名(必填)、密码(必填)、电话(非必填);
如果使用传统的SQL:

insert into user_info username, password, phone values(?,?,?);

当只填写用户名和密码时,再用上述的SQL语句就会报错,需要改成使用如下的SQL语句:

insert into user_info username, password values(?,?);

当用户填写用户名、密码和电话时使用上述的SQL语句也会报错

上述的文件需要使用动态SQL的方法,动态SQL的实现需要使用标签。

1.2 标签

  1. <if> 标签
    功能:根据条件动态拼接SQL片段,只有当条件满足时,标签内的SQL才会被包含。
    语法:

    <if test="条件">
        SQL片段
    </if>
    
  2. <trim> 标签
    功能:对SQL片段进行前缀或后缀的添加或移除,灵活处理SQL拼接中的多余关键字(如AND、OR、,等)。
    语法:

    	<trim prefix="前缀" suffix="后缀" prefixOverrides="移除的前缀" suffixOverrides="移除的后缀">
    	    SQL片段
    	</trim>
    
  3. <where> 标签
    功能:专门用于动态生成WHERE子句,自动处理多余的AND或OR,简化WHERE条件的拼接。
    语法:

    <where>
        SQL条件片段
    </where>
    
  4. <set> 标签
    功能:用于动态生成UPDATE语句中的SET子句,自动移除多余的逗号(,)。
    语法:

    <set>
        SQL更新片段
    </set>
    
  5. <sql> 和 <include> 标签
    功能:
    <sql>:定义可重用的SQL片段。
    <include>:引用中定义的片段。
    语法:

    	<!-- 定义SQL片段 -->
    	<sql id="片段ID">
    	    SQL内容
    	</sql>
    	
    	<!-- 引用SQL片段 -->
    	<include refid="片段ID" />
    

2.准备数据

2.1.MySQL数据准备

(1)创建数据库:

CREATE DATABASE mybatis_study DEFAULT CHARACTER SET utf8mb4;

(2)使用数据库

-- 使⽤数据数据
USE mybatis_study;

(3)创建用户表


-- 创建表[⽤⼾表]

CREATE TABLE `user_info` (
 `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
 `username` VARCHAR ( 127 ) NOT NULL,
 `password` VARCHAR ( 127 ) NOT NULL,
 `age` TINYINT ( 4 ) NOT NULL,
 `gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-⼥ 0-默认',
 `phone` VARCHAR ( 15 ) DEFAULT NULL,
 `delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
 `create_time` DATETIME DEFAULT now(),
 `update_time` DATETIME DEFAULT now() ON UPDATE now(),
 PRIMARY KEY ( `id` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; 

(4)添加用户信息

-- 添加⽤⼾信息
INSERT INTO mybatis_study.user_info( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_study.user_info( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_study.user_info( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_study.user_info( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );

2.2.创建对应的实体类

实体类的属性名与表中的字段名⼀⼀对应

@Data
public class UserInfo {

    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;

}

在这里插入图片描述
注意:在实际开发中不管什么实体类都要设置删除标志、创建时间、修改时间

3.<if>标签

3.1 在注解中使用

在注解中写标签时需要使用<script></script>标签

Mapper接口:

@Mapper
public interface UserInfoMapper {

    @Options(useGeneratedKeys= true, keyProperty = "id")
    @Insert("<script>"+
            "insert into user_info (username, password, age, "+
            "<if test='gender!=null'>gender,</if>"+
            "<if test='phone!=null'>phone</if>)"+
            "values(#{username}, #{password},#{age},"+
            "<if test='gender!=null'> #{gender},</if>"+
            "<if test='phone!=null'> #{phone}</if>)"
          +"</script>")
    Integer Insert(UserInfo userInfo);
}

说明:<if test='gender!=null'> #{gender},</if>中的gender如果不为空,则把#{gender},拼接到SQL字符串中;如果gender为空,则#{gender},不会在SQL语句中出现。

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Test
    void insert() {
        UserInfo userInfo =new UserInfo();
        userInfo.setUsername("333");
        userInfo.setPassword("333");
        userInfo.setAge(20);
        // 不填写gender
//        userInfo.setGender(1);
        userInfo.setPhone("3333");

        Integer count = userInfoMapper.Insert(userInfo);

        log.info("影响的行数:"+count + "  返回的id:"+ userInfo.getId());

    }

SQL中的结果:
在这里插入图片描述

如果测试代码改为如下:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Test
    void insert() {
        UserInfo userInfo =new UserInfo();
        userInfo.setUsername("333");
        userInfo.setPassword("333");
        userInfo.setAge(20);
        userInfo.setGender(1);
//        userInfo.setPhone("3333");

        Integer count = userInfoMapper.Insert(userInfo);

        log.info("影响的行数:"+count + "  返回的id:"+ userInfo.getId());

    }
}

运行结果:
在这里插入图片描述
可以看到Preparing中的SQL语句中多一个号,需要学习<trim>标签

3.2 在XML文件中实现

Mapper接口:

@Mapper
public interface UserInfoXMLMapper {

    //定义接口
    Integer insert(UserInfo userInfo);
}

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.mybatis.mapper.UserInfoXMLMapper">

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

测试类:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoXMLMapperTest {
	

    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;

    @Test
    void insert() {
        UserInfo userInfo= new UserInfo();
        userInfo.setUsername("4444");
        userInfo.setPassword("4444");
        userInfo.setAge(19);
        // 不填写gender
//        userInfo.setGender(1);
        userInfo.setPhone("4444");

        Integer count = userInfoXMLMapper.insert(userInfo);
        log.info("影响的行数:"+count + "  返回的主键:"+ userInfo.getId());
    }
}

运行结果:
在这里插入图片描述

MySQL插入的结果:
在这里插入图片描述

如果测试代码改为如下:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoXMLMapperTest {
	@Autowired
    private UserInfoXMLMapper userinfoXMLMapper;

    @Test
    void insert() {
        UserInfo userInfo =new UserInfo();
        userInfo.setUsername("333");
        userInfo.setPassword("333");
        userInfo.setAge(20);
        userInfo.setGender(1);
//        userInfo.setPhone("3333");

        Integer count = userInfoXMLMapper.Insert(userInfo);

        log.info("影响的行数:"+count + "  返回的id:"+ userInfo.getId());

    }
}

运行结果:
在这里插入图片描述
可以看到Preparing中的SQL语句中多一个号,需要学习<trim>标签

3.3 不使用<if>标签

有同学就会想,把所有的的字段都列出来,想插入什么值就在对象中设置什么值,使用<if>标签不是麻烦了吗!

如下面:

Mapper接口

@Mapper
public interface UserInfoMapper {
    @Insert("insert into user_info (username, password, age, gender, phone)"+
    "values(#{username}, #{password}, #{age}, #{gender}, #{phone})")
    Integer Insert(UserInfo userInfo);
}

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Test
    void insert() {
        UserInfo userInfo =new UserInfo();
        userInfo.setUsername("333");
        userInfo.setPassword("333");
        userInfo.setAge(20);
        // 不填写gender
//        userInfo.setGender(1);
        userInfo.setPhone("3333");

        Integer count = userInfoMapper.Insert(userInfo);

        log.info("影响的行数:"+count + "  返回的id:"+ userInfo.getId());

    }

运行结果:
在这里插入图片描述
插入SQL中的结果:
在这里插入图片描述
而使用<if>标签插入的结果是0,哪一个是对的呢?

看一下创建表user_info设置的默认值:
在这里插入图片描述
gender设置的默认值为0,为什么插入的是null呢?
答:创建的userInfo对象时会把所有属性初始化为默认值,String类型的默认值为null,所以把null作为参数传入了SQL中。

所以,动态SQL需要使用标签。

4.<trim>标签

4.1 标签的属性

当SQL语句中使用多个标签是会出现有,多余的问题,<trim>标签就可以派上用场了。

标签中有如下属性:
(1)prefix:表⽰整个语句块,以prefix的值作为前缀
(2)suffix:表⽰整个语句块,以suffix的值作为后缀
(3)prefixOverrides:表⽰整个语句块要去除掉的前缀
(4)suffixOverrides:表⽰整个语句块要去除掉的后缀

4.2 在注解中使用

Mapper接口:

@Mapper
public interface UserInfoMapper {

    @Options(useGeneratedKeys= true, keyProperty = "id")
    @Insert("<script>"+
            "insert into user_info ("+
                "<trim suffixOverrides=','>"+
                "username, password, age, "+
                "<if test='gender!=null'>gender,</if>"+
                "<if test='phone!=null'>phone</if>"+
                "</trim>"+
            ")"+
            "values("+
                "<trim suffixOverrides=','>"+
                "#{username}, #{password},#{age},"+
                "<if test='gender!=null'> #{gender},</if>"+
                "<if test='phone!=null'> #{phone}</if>"+
                "</trim>"+
            ")"+
            "</script>")
    Integer Insert(UserInfo userInfo);
}

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Test
    void insert() {
        UserInfo userInfo =new UserInfo();
        userInfo.setUsername("444");
        userInfo.setPassword("4444");
        userInfo.setAge(20);
        userInfo.setGender(1);
//        userInfo.setPhone("4444");

        Integer count = userInfoMapper.Insert(userInfo);

        log.info("影响的行数:"+count + "  返回的id:"+ userInfo.getId());

    }
}

运行结果:
在这里插入图片描述

MySQL:
在这里插入图片描述

Mapper最终的改进:

@Mapper
public interface UserInfoMapper {

    @Options(useGeneratedKeys= true, keyProperty = "id")
    @Insert("<script>"+
            "insert into user_info "+
                "<trim prefix='(' suffix=')' suffixOverrides=','>"+
                "username, password, age, "+
                "<if test='gender!=null'>gender,</if>"+
                "<if test='phone!=null'>phone</if>"+
                "</trim>"+
            "values "+
                "<trim prefix='(' suffix=')' suffixOverrides=','>"+
                "#{username}, #{password},#{age},"+
                "<if test='gender!=null'> #{gender},</if>"+
                "<if test='phone!=null'> #{phone}</if>"+
                "</trim>"+
            "</script>")
    Integer Insert(UserInfo userInfo);
}

4.3 在XML文件中使用

Mapper接口:

@Mapper
public interface UserInfoXMLMapper {

    //定义接口
    Integer insert(UserInfo userInfo);
}

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.mybatis.mapper.UserInfoXMLMapper">

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

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoXMLMapperTest {

    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;

    @Test
    void insert() {
        UserInfo userInfo= new UserInfo();
        userInfo.setUsername("5555");
        userInfo.setPassword("5555");
        userInfo.setAge(20);
        userInfo.setGender(1);
        //userInfo.setPhone("5555");

        Integer count = userInfoXMLMapper.insert(userInfo);
        log.info("影响的行数:"+count + "  返回的主键:"+ userInfo.getId());
    }
}

运行结果:
在这里插入图片描述

MySQL:
在这里插入图片描述

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.mybatis.mapper.UserInfoXMLMapper">

    <insert id = "insert"  useGeneratedKeys="true" keyProperty="id">
        insert into user_info
        <trim prefix="(" suffix=")" suffixOverrides="," >
            username,
            password,
            age,
            <if test="gender!=null">
                gender,
            </if>
            <if test="phone!=null">
                phone
            </if>
        </trim>

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

在以上 sql 动态解析时,会将第⼀个 部分做如下处理:

(1)基于prefix配置,开始部分加上配置,结束部分加上“(”
(2)基于suffix配置,结束部分加上“)”
(3)多个 组织的语句可能以,结尾,在最后拼接好的字符串还会以suffixOverrides 配置去掉最后⼀个,

5.<where>标签

需求: 传⼊的用户对象,根据属性做where条件查询,用户对象中属性不为 null 的,都为查询条件.。
如 username 为 “a”,则查询条件为 where username=“a”

5.1 不使用<where>标签

Mapper接口:

@Mapper
public interface UserInfoMapper {

    @Select("<script>"+
            "select id,username, password, age, gender, phone,delete_flag,create_time,update_time "+
            " from user_info "+
            " where "+
            "<if test ='username!=null'> username=#{username}</if>"+
            "<if test ='age!=null'> and age=#{age} </if> "+
            "<if test ='phone!=null'> and phone=#{phone}</if>"+
            "</script>"
    )
    List<UserInfo> queryAllUser(UserInfo userInfo);
 }

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Test
    void queryAllUser() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("lisi");
        userInfo.setAge(20);
        userInfo.setPhone("lisi");

        userInfoMapper.queryAllUser(userInfo);
    }
}

运行结果:
在这里插入图片描述

把测试代码改为:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Test
    void queryAllUser() {
        UserInfo userInfo = new UserInfo();
        //userInfo.setUsername("lisi");
        userInfo.setAge(20);
        userInfo.setPhone("lisi");

        userInfoMapper.queryAllUser(userInfo);
    }
}

运行结果:
在这里插入图片描述

把测试代码改为:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Test
    void queryAllUser() {
        UserInfo userInfo = new UserInfo();
        //userInfo.setUsername("lisi");
        //userInfo.setAge(20);
        //userInfo.setPhone("lisi");

        userInfoMapper.queryAllUser(userInfo);
    }
}

运行结果:
在这里插入图片描述
上述两个问题可以使用在where语句后添加 1=1(不推荐),也可以使用<where>标签解决

5.2 在注解中使用

Mapper接口:

@Mapper
public interface UserInfoMapper {

    @Select("<script>"+
            "select id,username, password, age, gender, phone,delete_flag,create_time,update_time "+
            " from user_info "+
            " <where>"+
            "<if test ='username!=null'>and username=#{username}</if>"+
            "<if test ='age!=null'> and age=#{age} </if> "+
            "<if test ='phone!=null'> and phone=#{phone}</if>"+
            "</where>"+
            "</script>"
    )
    List<UserInfo> queryAllUser(UserInfo userInfo);
}

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Test
    void queryAllUser() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("lisi");
        userInfo.setAge(20);
        userInfo.setPhone("lisi");

        userInfoMapper.queryAllUser(userInfo);
    }
}

运行结果:
在这里插入图片描述

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Test
    void queryAllUser() {
        UserInfo userInfo = new UserInfo();
        //userInfo.setUsername("lisi");
        userInfo.setAge(20);
        userInfo.setPhone("lisi");

        userInfoMapper.queryAllUser(userInfo);
    }
}

运行结果:
在这里插入图片描述

5.3 在XML文件中使用

Mapper接口:

@Mapper
public interface UserInfoXMLMapper {

    List<UserInfo> queryAllUser(UserInfo uerInfo);
}

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.mybatis.mapper.UserInfoXMLMapper">

    <resultMap id="baseMap" type="org.example.mybatis.model.UserInfo">
        <id column="id" property="id"></id>
        <result column="delete_flag" property="deleteFlag"></result>
        <result column="create_time" property="createTime"></result>
        <result column="update_time" property="updateTime"></result>
    </resultMap>

    <select id ="queryAllUser" resultType="org.example.mybatis.model.UserInfo">
        select id ,username, password, age, gender, phone,
               delete_flag, create_time ,
               update_time from user_info
        <where>
            <if test="username!=null">
                and username=#{username}
            </if>
            <if test="age!=null">
                and age=#{age}
            </if>
            <if test="phone!=null">
                and phone=#{phone}
            </if>
        </where>
    </select>
</mapper>

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoXMLMapperTest {

    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;

    @Test
    void queryAllUser() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("lisi");
        userInfo.setAge(20);
        userInfo.setPhone("lisi");

        List<UserInfo> list = userInfoXMLMapper.queryAllUser(userInfo);
        for (Object item : list) {
            log.info(item.toString());
        }
    }
}

运行结果:
在这里插入图片描述

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoXMLMapperTest {

    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;

    @Test
    void queryAllUser() {
        UserInfo userInfo = new UserInfo();
        //userInfo.setUsername("lisi");
        //userInfo.setAge(20);
        //userInfo.setPhone("lisi");

        List<UserInfo> list = userInfoXMLMapper.queryAllUser(userInfo);
        for (Object item : list) {
            log.info(item.toString());
        }
    }
}

运行结果:
在这里插入图片描述

6.<set>标签

需求: 根据传⼊的⽤⼾对象属性来更新⽤⼾数据,可以使⽤标签来指定动态内容.接⼝定义: 根据传⼊的⽤⼾ id 属性,修改其他不为 null 的属性

6.1 在注解中使用

Mapper接口:

@Mapper
public interface UserInfoMapper {

    @Update(
            "<script>"+
            "update user_info " +
                "<set>"+
                    "<if test='username!=null'> username=#{username}, </if>" +
                    "<if test='password!=null'> password=#{password},</if>"+
                    "<if test='age!=null'> age=#{age},</if>"+
                    "<if test='gender!=null'>gender=#{gender},</if>"+
                    "<if test='phone!=null'> phone=#{phone}, </if>"+
                "</set>"+
            "where id = #{id} "+
            "</script>"
    )
    Integer update(UserInfo userInfo);
}

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Test
    void update() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(3);
        userInfo.setUsername("33333");
        userInfo.setPhone("33333");

        userInfoMapper.update(userInfo);
    }
}

运行结果:
在这里插入图片描述
MySQL:
在这里插入图片描述

6.2 在XML文件中使用

Mapper接口:

@Mapper
public interface UserInfoXMLMapper {

    Integer update(UserInfo uerInfo);
}

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.mybatis.mapper.UserInfoXMLMapper">

    <resultMap id="baseMap" type="org.example.mybatis.model.UserInfo">
        <id column="id" property="id"></id>
        <result column="delete_flag" property="deleteFlag"></result>
        <result column="create_time" property="createTime"></result>
        <result column="update_time" property="updateTime"></result>
    </resultMap>

    <update id ="update">
        update user_info
        <set>
            <if test="username!=null">
                username=#{username},
            </if>
            <if test="password!=null">
                password=#{password},
            </if>
            <if test="age!=null">
                age=#{age},
            </if>
            <if test="gender!=null">
                gender=#{gender},
            </if>
            <if test="phone!=null">
                phone=#{phone},
            </if>
        </set>
        where id =#{id}
    </update>
</mapper>

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoXMLMapperTest {

    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;

    @Test
    void update() {
        UserInfo userInfo= new UserInfo();
        userInfo.setUsername("44444");
        userInfo.setPhone("44444");
        userInfo.setId(4);

        userInfoXMLMapper.update(userInfo);

    }
}

运行结果:
在这里插入图片描述
MySQL:
在这里插入图片描述

6.<foreach>标签

6.1 属性介绍

对集合进⾏遍历时可以使⽤该标签。标签有如下属性:
(1)collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象
(2)item:遍历时的每⼀个对象
(3)open:语句块开头的字符串
(4)close:语句块结束的字符串
(5)separator:每次遍历之间间隔的字符串

6.2 在注解中使用

需求: 根据多个userid, 删除⽤⼾数据

Mapper接口:

@Mapper
public interface UserInfoMapper {

    @Delete("<script>"+
            "delete from user_info where id in "+
            "<foreach collection='ids' item='id' separator=',' open='(' close=')' >"+
            "#{id}"+
            "</foreach>"+
            "</script>"
    )
    Integer delete(@Param("ids") List<Integer> ids);
}

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;


    @Test
    void delete() {
        List<Integer> list = Arrays.asList(29,30);

        userInfoMapper.delete(list);
    }

运行结果:
在这里插入图片描述

6.3 在XML文件中使用

需求: 根据多个userid, 删除⽤⼾数据

Mapper接口:

@Mapper
public interface UserInfoXMLMapper {

    // 定义接口
    // 注意,这里要用@param注解明确参数
    Integer delete(@Param("ids") List<Integer> ids);

}

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.mybatis.mapper.UserInfoXMLMapper">

    <resultMap id="baseMap" type="org.example.mybatis.model.UserInfo">
        <id column="id" property="id"></id>
        <result column="delete_flag" property="deleteFlag"></result>
        <result column="create_time" property="createTime"></result>
        <result column="update_time" property="updateTime"></result>
    </resultMap>

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

测试代码:

@Slf4j
@SpringBootTest //启动Sring 容器
class UserInfoXMLMapperTest {


    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;

    @Test
    void delete() {
        List<Integer> list = Arrays.asList(25,26,27,28);

        userInfoXMLMapper.delete(list);
    }
}

运行结果:
在这里插入图片描述

7.<sql>和<include>标签

在xml映射⽂件中配置的SQL,有时可能会存在很多重复的⽚段,此时就会存在很多冗余的代码

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

<sql></sql>定义可重⽤的SQL⽚段
<include>通过属性refid,指定包含的SQL⽚段

如:

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

通过<include>标签在需要的位置进行引用


<select id="queryAllUser" resultMap="BaseMap">
	select
	<include refid="allColumn"></include>
	from userinfo
</select>
	<select id="queryById" resultType="com.example.demo.model.UserInfo">
	select
	<include refid="allColumn"></include>
	from userinfo where id= #{id}
</select>
Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐