MyBatis 框架动态 SQL-if,where,foreach,复用代码片段(最后的比较鸡肋)

MyBatis 框架动态 SQL

内容列表
◼ 动态 SQL-if
◼ 动态 SQL-where
◼ 动态 SQL-foreach
◼ 动态 SQL-片段

动态 SQL,通过 MyBatis 提供的各种标签对条件作出判断以实现动态拼接 SQL 语句。这里的条件判

断使用的表达式为 OGNL 表达式。常用的动态 SQL 标签有 、 、 、 等。

MyBatis 的动态 SQL 语句,与 JSTL 中的语句非常相似。

动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行

查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行

排列组合,将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解决这样的问题

环境准备

创建新的 maven 项目,加入 mybatis , mysql 驱动依赖

创建实体类 Student , StudentDao 接口,StudentDao.xml , mybatis.xml , 测试类

使用之前的表 student。

在 mapper 的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等符号,最好将其转换为实体符号。否则,XML 可能会出现解析出错问题。特别是对于小于号(<),在 XML 中是绝不能出现的。否则解析 mapper 文件会出错。

实体符号表:

image-20221108124428277
项目结构目录如下:

1. 2 动态 SQL

接口方法:

List<Student> selectStudentIf(Student student);

mapper 文件:

<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 where 1=1
 <if test="name != null and name !='' ">
 and name = #{name}
 </if>
 <if test="age > 0 ">
 and age &gt; #{age}
 </if>
</select>

测试方法:

@Test
    public void testSelectStudentIf(){

        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao  =  sqlSession.getMapper(StudentDao.class);

        Student student  = new Student();
//        student.setName("李四");
//        student.setAge(18);

        student.setName("李四");
        student.setAge(20);
        List<Student> students = dao.selectStudentIf(student);
        for(Student stu:students){
            System.out.println("if==="+stu);
        }
    }

2.动态 SQL

标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后

的所有 条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL

出错。所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会

严重影响查询效率。

使用 标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加

where 子句。需要注意的是,第一个 标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错,

系统会将多出的 and 去掉。但其它 中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错

语法: 其他动态 sql

接口方法:

List<Student> selectStudentWhere(Student student);

mapper文件:

<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 <where>
 <if test="name != null and name !='' ">
 and name = #{name}
 </if>
 <if test="age > 0 ">
 and age &gt; #{age}
 </if>
 </where>
</select>

测试方法:

@Test
public void testSelectWhere() throws IOException {
 Student param = new Student();
 param.setName("李力");
 param.setAge(18);
 List<Student> studentList = studentDao.selectStudentWhere(param);
 studentList.forEach( stu -> System.out.println(stu));
}

结果如下:

3. 动态 SQL

标签用于实现对于数组与集合的遍历。对其使用,需要注意:

➢ collection 表示要遍历的集合类型, list ,array 等。

➢ open、close、separator 为对遍历内容的 SQL 拼接。

语法:

<foreach collection="集合类型" open="开始的字符" close="结束的字符" 
item="集合中的成员" separator="集合成员之间的分隔符">
 #{item 的值}
</foreach>
  • 遍历 List< 简单类型 >

    表达式中的 List 使用 list 表示,其大小使用 list.size 表示。

    需求:查询学生 id 是 1002,1005,1006

    接口方法:

    List<Student> selectStudentForList(List<Integer> idList);

    mapper文件

    <!--foreach使用1 , List<Integer>-->
        <select id="selectForeachOne" resultType="com.bjpowernode.domain.Student">
            select * from student where id in
            <foreach collection="list" item="myid" open="(" close=")" separator=",">
                      #{myid}
            </foreach>
    
        </select>

    测试方法:

    @Test
        public void testSelectForEach(){
            SqlSession sqlSession = MyBatisUtils.getSqlSession();
            StudentDao dao  =  sqlSession.getMapper(StudentDao.class);
    
            List<Integer> list = new ArrayList<>();
            list.add(1001);
            list.add(1002);
            list.add(1003);
    
            List<Student> students = dao.selectForeachOne(list);
            for(Student stu:students){
                System.out.println("foreach--one ==="+stu);
            }
        }

    测试结果如下:

  • 遍历 List< 对象类型 >

    在Dao中添加方法

    List<Student> selectStudentForList2(List<Student> stuList);

    编写mapper文件

    <select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student">
            <include refid="studentSql" />  where id in (
            <foreach collection="list" item="stu" >
                #{stu.id},
            </foreach>
            -1 )
        </select>

    测试方法如下:

4.动态 SQL 之代码片段

标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用

子标签。该 标签可以定义 SQL 语句中的任何部分,所以 子标签可以放在动态 SQL

的任何位置。

定义一个代码片段:

<!--定义sql片段-->
    <sql id="studentSql">
        select id,name, age, email from student
    </sql>

    <sql id="studentSqlOne">
         id,name, age, email
    </sql>

使用代码片段:

<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
        select <include refid="studentSqlOne" /> from student
        where id > 0
        <if test="name !=null and name !='' ">
           and name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
    </select>


    <!--
     where: <where> <if> <if>...</where>
    -->
    <select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
        <include refid="studentSql" />
        <where>
            <if test="name !=null and name !='' ">
                name = #{name}
            </if>
            <if test="age > 0">
                or age > #{age}
            </if>
        </where>
    </select>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值