当前位置: 代码网 > it编程>编程语言>Java > MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

2025年04月02日 Java 我要评论
动态sql详解动态sql是一种在运行时生成和执行sql语句的技术,广泛应用于处理复杂查询条件和动态数据需求。以下是动态sql的核心概念、常见用法及注意事项。一、动态sql的核心概念1.1 什么是动态s

动态sql详解

动态sql是一种在运行时生成和执行sql语句的技术,广泛应用于处理复杂查询条件和动态数据需求。以下是动态sql的核心概念、常见用法及注意事项。

一、动态sql的核心概念

1.1 什么是动态sql?

动态sql是一种灵活的sql编写方式,允许开发者在程序运行时根据条件生成sql语句,而不是在编译时固化。动态 sql 是mybatis的强大特性之一,能够完成不同条件下不同的 sql拼接。

1.2 动态sql的优点

  • 灵活性:根据不同条件生成不同的sql语句。
  • 复用性:减少重复代码,提高代码维护性。
  • 性能:在某些场景下可以优化查询性能。

1.3 动态sql的常见用途

  • 处理多条件查询。
  • 动态指定表名、字段或排序方式。
  • 处理批量操作。

二、动态sql的常见用法(xml方式)

数据库数据信息

2.1 < if > 标签

主要用于在动态sql中根据条件判断是否执行某个sql片段。它可以根据传入的参数或条件动态地添加或移除sql语句的一部分,从而实现灵活的查询需求。

userinfomapperxml.java 接口代码

 integer insertuserbysql(userinfo userinfo);

userinfomapper.xml 文件

    <insert id="insertuserbysql">
        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>

测试类没有插入gender的情况

    @test
    void insertuserbysql() {
        userinfo userinfo=new userinfo();
        userinfo.setusername("qq");
        userinfo.setpassword("qq");
        userinfo.setage(46);
        userinfo.setphone("465131");
        userinfomapperxml.insertuserbysql(userinfo);
    }

运行结果:

可以看到把gender这个字段使用if标签之后,这个字段就被移除了。

2.2< trim>标签

trim标签在动态sql中起到格式化sql语句的作用,允许开发者在生成sql时自动处理空格、换行符以及前缀后缀的添加。通过合理使用trim标签,可以简化动态sql的开发,提高代码的可读性和维护性,同时确保生成的sql语句高效且正确。

prefix:表示整个语句块,以prefix的值作为前缀
suffix:表示整个语句块,以suffix的值作为后缀
prefixoverrides:表示整个语句块要去除掉的前缀
suffixoverrides:表示整个语句块要去除掉的后缀

为了更好的了解trim标签的作用,先来个错误的示范。

xml.java 文件

integer insertuserbysql1(userinfo userinfo);

.xml文件

    <insert id="insertuserbysql1">
        insert into user_info
        <trim 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 suffix="(" prefix=")" >
            <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">
                #{phone}
            </if>
        </trim>
    </insert>

测试类

 @test
    void insertuserbysql1() {
        userinfo userinfo=new userinfo();
        userinfo.setusername("zhangs");
        userinfo.setpassword("123461");
        userinfo.setphone("7489");
        userinfomapperxml.insertuserbysql1(userinfo);

运行结果:

修改 .xml文件,通过trim标签给sql语句添加或者去除前后缀。

再进行测试;

可以看到成功了。

2.3 <where>标签

标签用于在动态sql中自动处理where子句的生成,简化多条件查询的开发。它能自动处理逻辑连接词(如and、or)以及去除多余的关键字,使得代码更加简洁和高效。

xml.java文件代码:

list<userinfo> selectbywhere();

.xml文件代码

  <select id="selectbywhere" resulttype="com.sliqvers.model.userinfo">
            select * from user_info
        <where>
            <if test="username!=null">
                and username=#{username}
            </if>
            <if test="password!=null">
                or password=#{password}
            </if>
        <if test="age!=null">
            and age=#{age}
        </if>
            <if test="phone!=null">
             or   phone=#{phone}
            </if>
        </where>
    </select>

测试类

  @test
    void selectbywhere() {
        userinfomapperxml.selectbywhere().stream().foreach(x-> system.out.println(x));
    }

观察数据库,这几个都有值,所以运行结果是全部

生成的sql:
当username和phonel都有值:
select * from user_info where username = ? and phone =?;
当只有username有值:
select * from user_info where username =?;
当两者都为null:
select * from user_info;

2.4<set>标签

标签在update语句中起到动态设置字段值的作用,自动处理set关键字和逗号,避免空更新。通过合理使用<set>标签,可以简化代码,提高sql执行效率,确保系统的安全性和稳定性。

xml.java文件

 integer upadteusersql(userinfo userinfo);

.xml文件

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

测试类:

    @test
    void upadteusersql() {
        userinfo userinfo=new userinfo();
        userinfo.setusername("sliqvers");
        userinfo.setpassword("111111");
        userinfo.setid(1);
        userinfomapperxml.upadteusersql(userinfo);
    }

运行结果:

生成的sql:
当username和password都有值:
update user_info set username = ?, email = ? where id = ?
当只有username有值:
update user_info set username = ? where id = ?
当只有password有值:
update users_info set password = ? where id = ?
当两者都为null:
update user_info where id = ?

2.5 <foreach> 标签

<foreach>标签在动态sql中起到遍历集合或数组的作用,生成in子句、批量insert或update等操作。通过合理使用标签,可以简化批量操作的sql拼接,提高开发效率和系统性能。同时,注意避免sql注入和空集合处理等问题,可确保动态sql的安全性和可靠性。

<foreach> 标签的属性

collection:必填,指定要遍历的集合名。
item:必填,指定遍历时的变量名。
open:可选,遍历开始时添加的字符串。
close:可选,遍历结束时添加的字符串。
separator:可选,遍历时的分隔符(默认",")。
index:可选,遍历时的索引变量。
select:可选,用于嵌套查询。

xml.java接口

  list<userinfo> selectbysql(list<integer> ids);

.xml文件

    <select id="selectbysql" resulttype="com.sliqvers.model.userinfo">
        select * from user_info where id in
        <foreach collection="ids" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </select>

测试类

    @test
    void selectbysql() {
        list<integer> ids=new arraylist<>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        userinfomapperxml.selectbysql(ids).stream().foreach(x-> system.out.println(x));
    }

运行结果:

生成的sql:
ids = [1, 2, 3] 时:
select * from user_info where id in (1, 2, 3)

2.6 <include>标签

在xml映射⽂件中配置的sql,有时可能会存在很多重复的片段,此时就会存在很多冗余的代码,我们可以对重复的代码片段进行抽取,将其通过 <sql> 标签封装到⼀个sql片段,然后再通过<include> 标签进行引用。

定义一个常用的where条件

<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 user_info
</select>

三、动态sql的注意事项

3.1 sql注入问题(搞破坏)

  • 风险:直接拼接用户输入可能导致sql注入。
  • 解决方案:使用参数化查询或orm框架(如mybatis)提供的安全功能。

3.2 performance

  • 执行计划缓存:动态sql可能导致数据库无法有效利用执行计划缓存。
  • 优化建议:尽量减少动态sql的使用场景,或者使用有限的条件组合。

3.3 动态sql的可读性和维护性

  • 复杂性:动态sql可能使代码更难阅读和维护。
  • 建议:合理分层代码,遵循编码规范。

四、总结

本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化 mybatis 配置,提升开发效率,确保 sql 的高效执行和安全性。学习这些技巧,帮助开发者更高效地构建和维护数据库交互层。

到此这篇关于mybatis 动态 sql 优化:标签的实战与技巧的文章就介绍到这了,更多相关mybatis 动态 sql 内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com