MyBatis日常笔记记录08--动态sql

一、什么是动态SQL

动态SQL,通过MyBatis提供的各种标签队条件作出判断以实现动态拼接SQL语句。这里的条件判断使用的表达式为OGNL表达式。常用的动态SQL标签有<if>、<where>、<choose/>、<foreach>等。

 

二、动态SQL的好处

动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行
查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行
排列组合,将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解决这样的问题。
 
三、常用的动态SQL标签方法演示
1.动态sql-if
<if>是判断条件的,
  语法<if test="判断java对象的属性值">
    部分sql语句  
</if>
  a.在接口中定义一个方法
 //动态sql-if,使用java对象作为参数
    List<Student> selectStudentIf(Student student);

   b.在mapper文件中编写映射信息

    <!--if
        <if test="使用参数java对象的属性值作为判断条件, 语法 属性=xxx值">
    -->
    <select id="selectStudentIf" resultType="com.example.domain.Student">
        select id, name, email, age from student
        where id>0 /*id > 0:避免第一条判断不执行时,sql语句会发生错误,如where and age>?(错误语法)*/
        <if test="name !=null and name !=''">
            and name = #{name}
        </if>
        <if test="age>0">
            and age > #{age}
        </if>
    </select>

   c.编写测试类

    @Test
    public void testSelectStudentsIf() {

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

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

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

 

 
2.动态sql-where
<where>标签用来包含多个<if>的,当多个if有一个成立时,<where>会自动增加一个where关键字,并去掉if中多余的 and,or等
  a.在接口中定义一个方法
    //动态sql-where
    List<Student> selectStudentWhere(Student student);
  b.在mapper文件中编写映射信息
    <!--
    where:<where><if></if>...<where>
    -->
    <select id="selectStudentWhere" resultType="com.example.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 > #{age}
            </if>
        </where>
    </select>
  c.编写测试类
    @Test
    public void testSelectStudentsWhere() {

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

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

        List<Student> students = dao.selectStudentWhere(student);
        for(Student stu : students){
            System.out.println("where=="+stu);
        }
    }

 

3.动态sql-foreach
<foreach>循环Java中的数值,list集合的,主要用在sql的in语句中
sql中语句是: select * from student where id in(1001,1002,1003);
 
在开始foreach前先了解然后通过字符串拼接的方法来得到上面的语句
    @Test
    public void testfor(){
        List<Integer> list = new ArrayList<>();
        list.add(1001);
        list.add(1002);
        list.add(1003);

        //select * from student where id in(1001,1002,1003)
        String sql = "select * from student where id in";

        StringBuilder builder = new StringBuilder("");

        //添加开始的 '('
        builder.append("(");
        for(Integer i : list){
            builder.append(i).append(",");
        }
        builder.deleteCharAt(builder.length()-1);
        //循环结尾 ')'
        builder.append(")");
        sql = sql + builder.toString();
        System.out.println("sql=="+sql);
    }

 

foreach本质上用到上面的字符串拼接的方法

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

</foreach>

collection : 表示接口中的方法参数的类型,如果是数值使用array,如果是List集合使用list
item :
自定义的,表示数组和集合成员变量
open : 循环开始时的字符
close : 循环结束时的字符
separator : 集合成员之间的分隔符

  
a.在接口中定义方法
    //foreach用法1
    List<Student> selectForeachOne(List<Integer> idList);

    //foreach用法2
    List<Student> selectForeachTwo(List<Student> stuList);

  b.在mapper文件中编写映射信息
    <!--foreach使用1,List<Integer>-->
    <select id="selectForeachOne" resultType="com.example.domain.Student">
        select * from student where id in
        <foreach collection="list" item="myid" open="(" close=")" separator=",">
                #{myid}
        </foreach>
    </select>


    <select id="selectForeachTwo" resultType="com.example.domain.Student">
        select * from student where id in
        <foreach collection="list" item="stu" open="(" close=")" separator=",">
                #{stu.id}
        </foreach>
    </select>

  c.编写测试类
    @Test
    public void testSelectStudentsForEachOne() {

        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);
        }
    }

    @Test
    public void testSelectStudentsForEachTwo() {

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

        List<Student> stuList = new ArrayList<>();
        Student s1 = new Student();
        s1.setId(1001);
        stuList.add(s1);

        Student s2 = new Student();
        s2.setId(1005);
        stuList.add(s2);

        List<Student> students = dao.selectForeachTwo(stuList);
        for(Student stu : students){
            System.out.println("foreach--two"+stu);
        }
    }

 
4.动态sql-代码片段
sql代码片段,就是复用一些语法
步骤:1.先定义 <sql id="自定义名称唯一">  sql语句 ,表名 , 字段等</sql>
   2.再使用,<include refid="id的值">
演示:
<!--定义sql片段-->
    <sql id="studentSql">
        select id, name, age, email from student
    </sql>

    <!--if
        <if test="使用参数java对象的属性值作为判断条件, 语法 属性=xxx值">
    -->
    <select id="selectStudentIf" resultType="com.example.domain.Student">
        /*select id, name, email, age from student*/
        <include refid="studentSql"/>
        where id>0 /*id > 0:避免第一条判断不执行时,sql语句会发生错误,如where and age>?(错误语法)*/
        <if test="name !=null and name !=''">
            and name = #{name}
        </if>
        <if test="age>0">
            and age > #{age}
        </if>
    </select>

 

posted @ 2021-07-06 13:16  Brack_Pearl  阅读(77)  评论(0编辑  收藏  举报