Mybatis动态 sql用法

目录

动态sql是什么:

Mybatis 的动态sql用法:

一、通过映射器配置文件来实现动态SQL

if标签

choose标签

where标签 

set标签 

trim标签

 可以代替set标签

可以代替where标签

foreach标签

bind标签

模糊查询 

sql标签

二、通过注解来实现动态SQL

1.脚本SQL

2.方法中构建SQL

用法:

3.SQL语句构造器


动态sql是什么:

根据不同条件拼接 SQL 语句,实现对数据库更准确的操作

Mybatis解决了JDBC的问题:

硬编码、SQL参数固定、代码重复度高、底层的一些技术

而MyBatis的动态sql用法就是解决SQL参数固定的问题

Mybatis 的动态sql用法:

1.映射器配置文件

2.注解

        脚本sql、在方法中构建sql、sql语句构造器

一、通过映射器配置文件来实现动态SQL

实现动态sql需要用到的标签

<if>、<choose>、<where>、<set>、<trim>、<foreach>、<bind>、<sql>

if标签

<!-- if 判断 相当于Java中的单条件分支 -->
语法:
    <if test="条件">满足条件的语句</if>
例:
<select id="findStudentif" resultType="Student" parameterType="Student">
     select * from Student
     where 1=1
     <!-- test 中填写 OGNL 表达式  对象图 导航语言  属性名 -->
     <if test="ssex != null">
          and ssex = #{ssex}
     </if>
</select>

choose标签

<!--choose 和 when , otherwise 是配套标签 类似于java中的switch,只会选中满足条件的一个-->
语法:
    <choose>
          <when test=“条件”>满足条件的语句</ when>
          <otherwise> 满足其他条件的语句 </otherwise>
    </choose>
例:
    <select id="findStudentchoose" resultType="Student" parameterType="Student">
          select sname,ssex,bithday,classid from Student
          where 1=1
          <choose>
               <when test="sname!=null"> and sname = #{sname} </when>
               <when test="ssex!=null"> and ssex = #{ssex} </when>
               <when test="birthday!=null"> and birthday = #{birthday} </when>
               <when test="classid!=0"> and classid = #{classid} </when>
               <otherwise>
                    and sid=7
               </otherwise>
          </choose>
     </select>

where标签 

语法:
    <where>
          <if test =”条件”> 满足条件的语句 </if>
    </where>
特点:
    1. 没有任何条件的时候 where标签整体不出现 也不会添加where关键词
    2. 将遇到的第一个 and 去掉,没有其他表达式的时候
    3. 当有条件的时候 会添加一个 Where 关键词
例:
    <select id="findStudentwhere" resultType="Student" parameterType="Student">
          select sname,bithday,ssex,classid from Student
          <where>
               <if test="ssex!=null">
                    and ssex=#{ssex}
               </if>
               <if test="classid!=0">
                    and classid=#{classid}
               </if>
          </where>
     </select>

set标签 

语法:
     <set>
          <if test =”条件”> 满足条件的语句 </if>
     </set>
特点:
    1. 添加一个set 关键词
    2. 将条件中的最后一个, 去掉
例:
    <update id="updateStu" 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}
          </where>
     </update>

trim标签

trim 万能标签 可以代替where标签 set标签
语法:
       prefix 开头添加一个 prefixOverrides 开头去掉一个
       suffix 结尾添加一个 suffixOverrides 结尾去掉一个 
    <trim prefix = "" suffixOverrides = "" prefixOverrides = "" suffix = ""></trim>

 可以代替set标签

例:
    <update id="updateStuTrim" parameterType="Student">
          update Student
          <trim prefix="set" suffixOverrides=",">
          <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>
          <where>
               sid=#{sid}
          </where>
          </trim>
     </update>

可以代替where标签

例:  
  <select id="findStudentwhere" resultType="Student" parameterType="Student">
          select sname,bithday,ssex,classid from Student
            <!-- 开头添加一个where 开头去掉一个 and -->
          <trim prefix = "where" suffixOverrides = "and">
               <if test="ssex!=null">
                    and ssex=#{ssex}
               </if>
               <if test="classid!=0">
                    and classid=#{classid}
               </if>
          </trim>
     </select>

foreach标签

foreach 标签  循环
     collection  集合用list  数组用array
     item        每个元素的存放起一个变量名
     open        开始添加一个
     close       结束添加一个
     separator   每个元素的分隔符
语法:
     <foreach item = "" index = "" collection = "" open = "" separator = "" close = ""> 
     </foreach>
例:
数组
     <!-- 查询 foreach array -->
     <select id="findStuForeach" resultType="Student">
          select * from Student where sid
          <foreach collection="array" item="aa" open=" in (" close=")" separator=",">
               #{aa}
          </foreach>
     </select>
集合
     <!-- 查询 foreach list -->
     <select id="findStuForeachList" resultType="Student">
          select * from Student where sid
          <foreach collection="list" item="aa" open=" in (" close=")" separator=",">
               #{aa}
          </foreach>
     </select>

bind标签

语法:
     <bind name = "" value = "_parameter"></bind>
name
     自定义变量的变量名
value
     自定义变量的变量值
_parameter
     传递进来的参数

模糊查询 

<!-- 模糊查询 -->
<select id="findStuBind" resultType="Student">
     <!-- 方式一 mybatis 推荐使用 -->
     <bind name="bb" value="_parameter+'%'"/>
     select * from Student where sname like #{bb}
     <!-- 方式二  -->
     select * from Student where sname like #{v}"%"
     <!-- 方式三 -->
     select * from Student where sname like concat(#{v},'%')
     <!-- 方式四 直接传 王% -->
     select * from Student where sname like #{v}
     <!-- 方式五 不推荐
             #{} 可以防止SQL注入
             ${} 字符串替换,不能防止SQL注入
     -->
     select * from Student where sname like '${v}%'
</select>

sql标签

语法:
     <sql id="不能重复"> 需要替代的sql片段 </sql>
调用:
    <include refid="定义的sql片段名"></include>
通过调用可以直接当被定义的sql语句使用
例:
    <sql id="stusql">select * from Student</sql>     
        <select id="findStudentif" resultType="Student" parameterType="Student"> 
        <include refid="stusql"></include>          
            where 1=1          
        <if test="ssex != null">
               and ssex=#{ssex}
        </if>
        <if test="classid != 0">
               and classid=#{classid}
        </if> 
        </select>

二、通过注解来实现动态SQL

注解动态sql有三种

1.脚本SQL

        在sql语句中加入<script></script>标签,按照之前sqlmap中的动态sql的样式书写

例:
public interface StudentMapper3 {
     //脚本SQL
     @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> findAllStudent3(Student s);
}

2.方法中构建SQL

需用到

        @SelectProvider

                创建动态的 SELECT 语句

        @InsertProvider

                创建动态的 INSERT 语句

        @UpdateProvider

                创建动态的 UPDATE 语句

        @DeleteProvider

                创建动态的 DELETE 语句

这些方法

用法:

1.创建 SQL 语句类

     该类包含需要动态生成的SQL 语句;

2.创建Mapper接口类

     该类和配置文件的接口文件一样,用来处理数据库操作;

3.利用上述4种方法

     将 SQL 语句类和 Mapper 接口类关联,利用方法中的 type 属性和 method 属性;

4.测试验证

     编写测试类,测试动态生成的SQL 语句是否准确。

例:
     //修改
     @UpdateProvider(type = StuLei.class ,method = "updateStudentLei")
     public int updateStudent3(Student s);

     class StuLei{
          //修改
          public String updateStudentLei(Student s) {

               String sql = "update Student set ";
               if(s.getBirthday()!=null) {
                    sql+="birthday = #{birthday},";
               }
               if(s.getClassid() != 0 ) {
                    sql+="classid =#{classid},";
               }
               if(s.getSname()!=null) {
                    sql+="sname = #{sname},";
               }
               if(s.getSsex()!=null) {
                    sql+="ssex = #{ssex},";
               }

               sql = sql.substring(0,sql.length()-1);
               sql+=" where sid=#{sid}";
               return sql;
          }

注:这种方法 主要问题是号和 and 的处理 

特点:

        在接口中定义内部类,来构建需要的动态sql语句,比使用标签的方式结构更加清晰

3.SQL语句构造器

功能

     解决 Java 代码中嵌入 SQL 语句,通过简单地创建一个实例来调用方法生成SQL语句

特点

     没有过多的使用类如 and的连接词 

SQL 语句构造器的常用方法

属性名

说明

SELECT

开始或插入到 SELECT 子句,可以被多次调用,参数也会添加到 SELECT子句。

FROM

开始或插入到 FROM 子句,可以被多次调用,参数也会添加到 FROM 子句

WHERE

插入新的 WHERE 子句条件,可以多次被调用

OR / AND

使用 OR / AND 来分隔当前的 WHERE 子句的条件

DELETE_FROM

开始一个 delete 语句并指定需要从哪个表删除的表名。

INSERT_INTO

开始一个 insert 语句并指定需要插入数据的表名

VALUES

插入到 insert 语句中。第一个参数是要插入的列名,第二个参数则是该列的值。

UPDATE

开始一个 update 语句并指定需要更新的表名

 SET

针对 update 语句,插入到 "set" 列表中

注:关键字必须全部大写 

例:
public interface StudentMapper {

    //删除
    @DeleteProvider(type = StuLei.class,method = "gzqDeleteStudent")
    public int deleteStudent3(int sid);
    //新增
    @InsertProvider(type = StuLei.class,method = "gzqAddStudent")
    public int addStudent3(Student s);
    //查询
    @SelectProvider(type = StuLei.class,method = "gzqSelectStudent")
    public List<Student> SelectStudent3(Student s);
    
    class StuLei{
        
        //删除
        public String gzqDeleteStudent(int sid) {
            return new SQL() {
                {
                    DELETE_FROM("student");
                    WHERE("sid = #{sid}");
                }
            }.toString();
        }
        //添加
        public String gzqAddStudent(Student s) {
            return new SQL() {
                {
                    INSERT_INTO("student");
                    VALUES("birthday","#{birthday}");
                    VALUES("sname","#{sname}");
                    VALUES("ssex","#{ssex}");
                    VALUES("classid","#{classid}");
                }
            }.toString();
            
        }
        //查询
        public String gzqSelectStudent(Student s) {
            return new SQL() {
                {
                    SELECT("sid,sname,birthday,ssex,classid");
                    FROM("student");
                    if(s.getClassid() != 0) {
                        WHERE("classid = #{classid}");
                    }
                    if(s.getSsex() != null) {
                        WHERE("ssex = #{ssex}");
                    }
                }
            }.toString();
        }
    }
}

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值