Mybatis 动态sql

       

目录

一、核心特点:

二、XML配

置方式实现动态sql

四、mybatis 动态sql xml配置与注解的优缺点 

五、使用建议:


         mybatis 动态sql是一种能够根据不同参数条件动态生成、拼接 SQL 语句的技术,它允许在 SQL 语句中嵌入条件判断、循环等逻辑,使得能根据运行时的参数情况自动调整最终执行的 SQL 结构。MyBatis 提供了两种实现动态 SQL 的方式:XML 配置和注解。这两种方式各有特点,适用于不同的场景。

一、核心特点:

1、条件性拼接:根据参数是否为空、是否满足特定条件,决定是否拼接对应的 SQL 片段(如 WHERE 子句中的条件)。

2、灵活性:无需手动拼接 SQL 字符串,避免因参数变化导致的语法错误(如多余的 AND/OR 关键字)。

3、安全性:结合 MyBatis 的参数绑定机制,防止 SQL 注入风险。

4、复用性:支持通过 <sql> 标签定义可复用的动态 SQL 片段,减少冗余。

二、XML配

置方式实现动态sql

        XML 方式是 MyBatis 最传统也最常用的动态 SQL 实现方式,通过<if><choose><when><othewise><trim><where><set><foreach> 等标签来实现动态 SQL 逻辑。 

1、<where>标签:

(1)<where>作用:当where标签有内容时,会添加一个where 当where标签没有内容时不添加where , 当where标签会去掉紧跟在where关键词后面的第一个and或者or之类的连接符 

         <if>元素:< if test =”条件”> 语句 </if> 满足条件 执行语句

(2)使用:

 <!--    sql  片段 可以截取sql片段   -->
    <sql id="stusql">
        sid
        ,sname,birthday,ssex,classid
    </sql>
    <select id="getStudent" resultType="student">
        select<include refid="stusql"></include> from Student
        <where>
            <if test="ssex !=null ">
                and ssex = #{ssex}
            </if>
            <if test="classid != 0 ">
                and classid = #{classid}
            </if>
        </where>
    </select>

2、<choose>标签

(1)作用:只能有一个条件被使用 使用满足的第一个条件 条件都不满足使用 otherwise 有优先级

        <when>元素:< when  test =”条件”> 语句 </when> 满足条件 执行语句 一个choose里面最多执行一个when

(2)使用:

<select id="getStudentChoose" resultType="student">
        select <include refid="stusql"></include> from Student
        <where>
                 <choose>
                <when test="ssex!=null">
                    ssex=#{ssex}
                </when>
                <when test="classid!=0">
                    classid=#{classid}
                </when>
                <otherwise>
                    sid=10
                </otherwise>
            </choose>
        </where>
    </select>

3、<set>标签

(1)作用:set 会自动添加一个set关键词 并去除最后一个逗号,

(2)使用:

<update id="updateStudent" parameterType="student">
        update student
        <set>
            <if test="sname!=null">
                sname=#{sname},
            </if>
            <if test="birthday!=null">
                birthday=#{birthday},
            </if>
            <if test="ssex!=null">
                ssex=#{ssex},
            </if>
            <if test="classid!=0">
                classid=#{classid},
            </if>
        </set>
        where sid=#{sid}
    </update>

4、<trim>标签(万能标签)效率不高

(1)作用:可以实现自由拼接

<trim prefix="" prefixOverrides="" suffix="" suffixOverrides=""></trim>

//<!-- prefix="" 开始之前 添加一个什么 prefixOverrides="" 开始之前去掉一个什么 suffix="" 结束之前添加一个什么 suffixOverrides="" 结束之前去掉一个什么 -->

(2)使用

 <select id="getStudentTrim" parameterType="student" resultType="student">
        select <include refid="stusql"></include> from Student
         <trim prefix="where" prefixOverrides="and" suffix="" suffixOverrides="">
            <if test="ssex!=null">
                and ssex=#{ssex}
            </if>
            <if test="classid!=0">
                and classid=#{classid}
            </if>
        </trim>
    </select>

5、<foreach>标签

(1)作用:可以将数组集合等遍历拼接在sql语句上

<foreach collection="" item="" index="" open="" close="" separator="">  </foreach>

item 循环中的当前元素;

collection 方法传递的参数,一个数组或者集合;

close 以什么符号结束将这些集合元素包装 起来;

index 当前循环元素的位置下标;

open 以什么符号开始将这些集合元素包装 起来;

separator 各个元素的间隔符号

(2)使用

 <select id="getStudentList" resultType="student">
        select<include refid="stusql"></include> from Student
        <where>
            sid in
            <foreach collection="list" item="x" open="(" close=")" separator=",">
                #{x}
            </foreach>
        </where>
    </select>

6、<bind>标签

(1)作用:可以定义变量 在sql语句中引用

<bind name="" value=""></bind>

name:变量名

value: 值

(2)使用:

<select id="getStudentBySnameLike" resultType="student" parameterType="String">
        <bind name="li" value="'%'+_parameterType+'%'"/>
        select * from student where sname like #{li};

    </select>

三、注解方式(动态sql)

1、使用sql脚本编写动态sql 使用<script>

@Select({"<script>" + "select * from student " +
            "<where>" +
            "<if test=\"ssex !=null \"> and ssex= #{ssex}</if>" +
            "<if test=\"classid !=0 \"> and classid =#{classid}</if>" +
            "</where>" + "</script>"})
    public List<Student> getstudent(Student s);

2、手动构建sql语句(不使用构造器)需要使用@xxxxtProvider(type= ,method=" ")注解

   type: 类.class

   method:类中的方法引用:

    @SelectProvider(type = StuSql.class, method = "getStudentSqlSelect")
    public List<Student> getStudentFunc(Student s);


    @SelectProvider(type = StuSql.class, method = "getStudentSqlSelectGaoZao")
    public List<Student> getStudentGouZao(Student s);

    @InsertProvider(type = StuSql.class,method = "addStudentSqlInsertGuoZao")
    public int insertStudentGuoZao(Student s);

    @DeleteProvider(type = StuSql.class,method = "deleteStudentSqlInsertGuoZao")
    public int deleteStudentGuoZao(int sid);

    @UpdateProvider(type = StuSql.class,method = "updateStudentSqlInsertGuoZao")
    public int updateStudentGuoZao(Student s);


    class StuSql {
        //第一种手动构建
        public String getStudentSqlSelect(Student s) {
            String sql = "select * from Student where 1=1 ";
            if (s.getSsex() != null) {
                sql += "and ssex =#{ssex}";
            }
            if (s.getClassid() != 0) {
                sql += "and classid =#{classid}";
            }
            return sql;
        }

       }

3、使用构造器:需要使用@xxxxtProvider(type= ,method=" ")注解

   type: 类.class

   method:类中的方法引用:

(1) SELECT 查询:

    @SelectProvider(type = StuSql.class, method = "getStudentSqlSelectGaoZao")
    public List<Student> getStudentGouZao(Student s);

 
    class StuSql {
         //使用构造器
        public String getStudentSqlSelectGaoZao(Student s) {
            return new SQL() {
                {
                    SELECT("sid");
                    SELECT("sname,birthday");
                    SELECT("ssex", "classid");
                    FROM("student");
                    if (s.getSsex() != null) {
                        WHERE("ssex=#{ssex}");
                    }
//                    OR()  默认and 除非手动加OR()
                    if (s.getClassid() != 0) {
                        WHERE("classid=#{classid}");
                    }
                }
            }.toString();
        }

      
    }

(2)INSERT: 增加

    @InsertProvider(type = StuSql.class,method = "addStudentSqlInsertGuoZao")
    public int insertStudentGuoZao(Student s);


    class StuSql {
        
        public String addStudentSqlInsertGuoZao(Student s){
            return new SQL(){
                {
                    INSERT_INTO("student");
                    if(s.getSid()!=0){
                        VALUES("sid","#{sid}");
                    }
                    if(s.getSname()!=null){
                        VALUES("sname","#{sname}");
                    }
                    if(s.getBirthday()!=null){
                        VALUES("birthday","#{birthday}");
                    }
                    if(s.getSsex()!=null){
                        VALUES("ssex","#{ssex}");
                    }
                    if(s.getClassid()!=0){
                        VALUES("classid","#{classid}");
                    }
                }
            }.toString();
        }

    }

(3)DELETE : 删除

    @DeleteProvider(type = StuSql.class,method = "deleteStudentSqlInsertGuoZao")
    public int deleteStudentGuoZao(int sid);

    class StuSql {

        public String deleteStudentSqlInsertGuoZao(int sid){
            return new SQL(){
                {
                DELETE_FROM("student");
                WHERE("sid=#{sid}");
            }
            }.toString();
        }
     
    }

(4)UPDATE:修改


    @UpdateProvider(type = StuSql.class,method = "updateStudentSqlInsertGuoZao")
    public int updateStudentGuoZao(Student s);


    class StuSql {
       
        public String updateStudentSqlInsertGuoZao(Student s){
            return new SQL(){
                {
                   UPDATE("student");
                    if(s.getSname()!=null){
                        SET("sname = #{sname}");
                    }
                    if(s.getBirthday()!=null){
                        SET("birthday = #{birthday}");
                    }
                    if(s.getSsex()!=null){
                        SET("ssex = #{ssex}");
                    }
                    if(s.getClassid()!=0){
                        SET("classid = #{classid}");
                    }
                    WHERE("sid=#{sid}");
                }
            }.toString();
        }
    }

四、mybatis 动态sql xml配置与注解的优缺点 

方式优点缺点
XML 配置1. SQL 与代码分离,结构清晰,可读性强;
2. 支持复杂动态逻辑和片段复用;
3. 便于 SQL 优化和团队协作;
4. 无需重新编译即可生效。
1. 需要维护额外的 XML 文件,项目结构稍显复杂;
2. 简单逻辑可能显得繁琐。
注解方式1. 无需 XML 文件,代码集中,开发便捷;
2. 适合简单场景,学习成本低;
3. 与 Java 代码紧密结合,便于快速定位。
1. 复杂 SQL 逻辑导致代码臃肿,可读性差;
2. 循环、嵌套等操作需手动实现,易出错;
3. 修改 SQL 需重新编译,不适合频繁变更场景。

五、使用建议:

1、选择 XML 配置:当项目中存在复杂动态 SQL(如多条件组合查询、批量操作)、需要频繁优化 SQL 或团队协作时,XML 方式的可维护性和清晰性更具优势。

2、适当使用注解方式:对于简单的动态逻辑(如单表的基础 CRUD)或轻量级项目,注解方式可以简化配置,提高开发效率。

3、混合使用策略:在实际项目中,可根据场景灵活选择 —— 核心复杂逻辑用 XML,简单辅助逻辑用注解,但需保持团队风格统一。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呼哧呼哧.

栓Q!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值