mybatis(二)

一,动态SQL

动态SQL是Mybatis的强大特性之一,能够完成不同条件下不同的sql拼接

1.1 <if>标签

在注册用户的时候,可能会有这样⼀个问题:

注册分为两种字段:必填字段和非必填字段,那如果在添加用户的时候有不确定的字段传入,程序应该如何实现呢?

这个时候就需要使用动态标签来判断了,比如添加的时候性别gender为非必填字段,具体实现如 下:

接口定义:

java 复制代码
    Integer insertUserInfoByCondition(UserInfo userInfo);

Mapper.xml实现:

java 复制代码
 <insert id="insertUserInfoByCondition">
        insert into user_info(username,`password`,age,
        <if test="gender!=null">
            gender,
        </if>
        phone)
        values (#{username},#{password},#{age},
        <if test="gender!=null">
            #{gender},
        </if>
       #{phone})
    </insert>

不加<if>标签时,运行结果如下:

未传参的会赋值为null

加了标签之后,运行结果为:

其中未传参的会赋上默认值

或者使用注解方式

java 复制代码
@Insert("""
            <script>
            insert into user_info
                <trim suffixOverrides="," prefix="(" suffix=")">
                    <if test="username!=null">username,</if>
                    <if test="password!=null">`password`,</if>
                    <if test="age!=null">age,</if>
                    <if test="gender!=null">gender,</if>
                    <if test="phone!=null">phone</if>
                </trim>
                values
                <trim suffixOverrides="," prefix="(" suffix=")">
                    <if test="username!=null">#{username},</if>
                    <if test="password!=null">#{password},</if>
                    <if test="age!=null">#{age},</if>
                    <if test="gender!=null">#{gender},</if>
                    <if test="phone!=null">#{phone}</if>
                </trim>
            </script>
            """)
    Integer insertUserInfoByCondition(UserInfo userInfo);

注意test中的gender,是传入对象中的属性,不是数据库字段(上述例子中,test里面是判断条件,判断 #{gender}是否为空)

Q: 可不可以不进行判断,直接把字段设置为null呢?

A: 不可以, 这种情况下,如果gender字段有默认值,就会设置为默认值

1.2 <trim>标签

之前的插入用户功能,只是有⼀个gender字段可能是选填项,如果有多个字段,⼀般考虑使用标签结合标签,对多个字段都采取动态生成的方式。

标签中有如下属性:

• prefix:表示整个语句块,以prefix的值作为前缀

• suffix:表示整个语句块,以suffix的值作为后缀

• prefixOverrides:表示整个语句块要去除掉的前缀

• suffixOverrides:表示整个语句块要去除掉的后缀

调整Mapper.xml的插入语句为:

java 复制代码
    <insert id="insertUserInfoByCondition">
        insert into user_info
        <trim suffixOverrides="," prefix="(" suffix=")">
            <if test="username!=null">
                username,
            </if>
            <if test="password!=null">
                `password`,
            </if>
            <if test="age!=null">
                age,
            </if>
            <if test="gender!=null">
                gender,
            </if>
            <if test="phone!=null">
                phone
            </if>
        </trim>
        values
        <trim suffixOverrides="," prefix="(" suffix=")">
            <if test="username!=null">
                #{username},
            </if>
            <if test="password!=null">
                #{password},
            </if>
            <if test="age!=null">
                #{age},
            </if>
            <if test="gender!=null">
                #{gender},
            </if>
            <if test="phone!=null">
                #{phone}
            </if>
        </trim>
    </insert>

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

• 基于 prefix 配置,开始部分加上 (

• 基于 suffix 配置,结束部分加上 )

• 多个组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于suffixOverrides 配置去掉最后一个,

• 注意 username 是传入对象的属性

1.3 <where>标签

需求:传⼊的⽤⼾对象,根据属性做where条件查询,⽤⼾对象中属性不为null的,都为查询条件.如 username为"a",则查询条件为whereusername="a"

接⼝定义:

java 复制代码
List<UserInfo> queryByCondition();

Mapper.xml实现:

java 复制代码
<select id="queryByCondition" resultType="com.luoyaoyun.mybatisdemo.model.UserInfo">
<!--                SELECT * FROM user_info WHERE 1=1-->
<!--                <trim prefixOverrides="AND">-->
<!--                    <if test="age!=null">-->
<!--                        age = #{age}-->
<!--                    </if>-->
<!--                    <if test="gender!=null">-->
<!--                        AND gender = #{gender}-->
<!--                    </if>-->
<!--                    <if test="deleteFlag!=null">-->
<!--                        AND delete_flag = #{deleteFlag}-->
<!--                    </if>-->
<!--                </trim>-->

        SELECT * FROM user_info
        <where>
            <if test="age!=null">
                age = #{age}
            </if>
            <if test="gender!=null">
                AND gender = #{gender}
            </if>
            <if test="deleteFlag!=null">
                AND delete_flag = #{deleteFlag}
            </if>
        </where>

    </select>

上述代码有两种方法,其中where标签就完成了第一种方法中实现的两种方法,1)去除最前面的and 2)如果查询条件为空,则不添加where关键字

<where>只会在⼦元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的AND或 OR

以上标签也可以使用

复制代码
<trim prefix="where" prefixOverrides="AND">

替换,但是此种情况下,当⼦元素都没有内容时,where关键字也会保留

1.4 <set>标签

需求:根据传入的⽤⼾对象属性来更新⽤⼾数据,可以使⽤标签来指定动态内容

接⼝定义:根据传⼊的⽤⼾id属性,修改其他不为null的属性

java 复制代码
Integer updateUserByCondition(UserInfo userInfo);

Mapper.xml

java 复制代码
<update id="updateByCondition">
<!--                update user_info-->
<!--                set-->
<!--                <trim suffixOverrides=",">-->
<!--                    <if test="username!=null">-->
<!--                        username=#{username},-->
<!--                    </if>-->
<!--                    <if test="age!=null">-->
<!--                        age= #{age},-->
<!--                    </if>-->
<!--                    <if test="gender!=null">-->
<!--                        gender = #{gender},-->
<!--                    </if>-->
<!--                    <if test="deleteFlag!=null">-->
<!--                        delete_flag = #{deleteFlag}-->
<!--                    </if>-->
<!--                </trim>-->
<!--                where id= #{id}-->

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

    </update>

<set> : 动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号.(用于update语句中)

1.5 <foreach>标签

对集合进⾏遍历时可以使⽤该标签。标签有如下属性:

• collection:绑定⽅法参数中的集合,如List,Set,Map或数组对象

• item:遍历时的每⼀个对象

• open:语句块开头的字符串

• close:语句块结束的字符串

• separator:每次遍历之间间隔的字符串

需求:根据多个userid,删除用户数据

接⼝⽅法:

java 复制代码
void deleteByIds(List<Integer> ids);

UserInfoMapper.xml

java 复制代码
 <delete id="batchDelete">
        delete from user_info
        where id in
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </delete>

1.6 <include>标签

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

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

<include>标签进⾏引⽤。

  • <sql>:定义可重⽤的SQL⽚段
  • <include>:通过属性refid,指定包含的SQL⽚段
java 复制代码
<sql id="allColumn">
    id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>

通过<include>标签在原来抽取的地⽅进⾏引⽤。

java 复制代码
<select id="queryAllUser" resultMap="BaseMap">
    select
    <include refid="allColumn"></include>
    from user_info
</select>
<select id="queryById" resultType="com.example.demo.model.UserInfo">
    select
    <include refid="allColumn"></include>
    from user_info where id= #{id}
</select>

二. 案例练习

2.1 表白墙

2.1.1 数据准备

sql 复制代码
DROP TABLE IF EXISTS message_info;
CREATE TABLE `message_info` (
    `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
    `from` VARCHAR ( 127 ) NOT NULL,
    `to` VARCHAR ( 127 ) NOT NULL,
    `message` VARCHAR ( 256 ) NOT 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;

ON UPDATE now():当数据发生更新操作时,自动把该列的值设置为now(),

now() 可以替换成其他获取时间的标识符,⽐如:CURRENT_TIMESTAMP(),LOCALTIME()等

2.1.2 引入MyBatis和MySQL驱动依赖

修改pom文件:

java 复制代码
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>

2.1.4 编写后端代码

Model

java 复制代码
@Data
public class MessageInfo {
    private Integer id;
    private String from;
    private String to;
    private String message;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;

}

MessageInfoMapper

java 复制代码
@Mapper
public interface MessageInfoMapper {
    @Select("select `id`, `from`, `to`, `message` from message_info where delete_flag=0")
    List<MessageInfo> queryAll();
    @Insert("insert into message_info (`from`,`to`, `message`) values(#{from},#{to},#{message})")
    Integer addMessage(MessageInfo messageInfo);
}

MessageInfoService

java 复制代码
@Service
public class MessageInfoService {
    @Autowired
    private MessageInfoMapper messageInfoMapper;
    
    public List<MessageInfo> queryAll() {
        return messageInfoMapper.queryAll();
    }
    public Integer addMessage(MessageInfo messageInfo) {
        return messageInfoMapper.addMessage(messageInfo);
    }
}

MessageController

java 复制代码
@RequestMapping("/message")
@RestController
public class MessageController {

    @Autowired
    private MessageInfoService messageInfoService;

    @GetMapping("/getList")
    public List<MessageInfo> getList(){
        return messageInfoService.queryAll();
    }

    @PostMapping(value = "/publish")
    public boolean publish(MessageInfo messageInfo) {
        System.out.println(messageInfo);
        if (StringUtils.hasLength(messageInfo.getFrom())
                && StringUtils.hasLength(messageInfo.getTo())
                && StringUtils.hasLength(messageInfo.getMessage())) {
            messageInfoService.addMessage(messageInfo);
            return true;
        }
        return false;
    }

}

访问这个网址即可

相关推荐
西凉的悲伤1 小时前
Guava-Retrying 重试框架详解
java·guava·重试框架·guava-retrying
yyuuuzz1 小时前
云服务器搭建个人博客记录:一次访问超时的复盘
运维·服务器·数据库
SunnyDays10111 小时前
使用 Java 高效管理 Excel 批注:添加、读取、修改和删除
java·开发语言·excel
花间相见1 小时前
【计算基础|MySQL06】MySQL 架构与一条 SQL 的旅程
数据库·后端
oradh1 小时前
Oracle 分析函数使用总结
数据库·oracle
updayday8542 小时前
印染产线电脑进程异常占用资源却要逐台排查 - Ping64 远程进程管理
大数据·网络·数据库·安全·智能路由器
const_qiu2 小时前
第 2.5 章 2.5.8:质量关 —— 安全审查、UI/UX 审查与踩坑复盘
java·人工智能·安全·ui·ux
QYRdata2 小时前
年复合增长率8.2%!2026-2032年数据库开发服务赛道增长动能持续释放
数据库·服务发现·数据库开发·恒州博智
坊钰2 小时前
【LangGraph框架入门级】12. 人机交互:interrupt 中断与 Command 恢复
开发语言·数据库·python·人机交互·ai编程·langgraph