zoukankan      html  css  js  c++  java
  • 【Mybatis】MyBatis之动态SQL(六)

      MyBatis 的强大特性之一便是它的动态 SQL,本章介绍动态 SQL

      查看本章,请先阅读【Mybatis】MyBatis对表执行CRUD操作(三)

      本例表结构

    1 CREATE TABLE `employee` (
    2   `id` int(11) NOT NULL AUTO_INCREMENT,
    3   `last_name` varchar(255) DEFAULT NULL,
    4   `gender` char(1) DEFAULT NULL,
    5   `email` varchar(255) DEFAULT NULL
    6   PRIMARY KEY (`id`)
    7 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    if

      if标签:用于逻辑判断,其中test属性,填写的是判断表达式(OGNL)

      示例

      1、EmployeeMapper新增Sql如下:

     1 <!-- if:判断 -->
     2 <select id="testConditionIf"
     3     resultType="com.hd.test.pojo.Employee">
     4     select id, last_name lastName, gender from employee
     5     <!-- 
     6         test:判断表达式(OGNL) OGNL参照PPT或者官方文档。 
     7         c:if test 从参数中取值进行判断 遇见特殊符号应该去写转义字符: &&:
     8         
     9      -->
    10     where 1 = 1
    11     <if test="id != null">
    12         AND id = #{id}
    13     </if>
    14     <!-- 表达式中,字符串使用''单引号引起来 -->
    15     <if test="lastName != null and lastName.trim() != ''">
    16         AND last_name = #{lastName}
    17     </if>
    18     <!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
    19     <if test="gender==0 or gender==1">
    20         AND gender = #{gender}
    21     </if>
    22     <!-- 转义字符: &amp;&amp; == &&    &quot;&quot; == ""-->
    23     <if test="email != null &amp;&amp; lastName!=&quot;&quot;">
    24         AND email = #{email}
    25     </if>
    26 </select>

       2、EmployeeMapper接口中,新增方法

    1 public List<Employee> testConditionIf(Employee employee);

      3、测试方法

     1 @Test
     2 public void test001() throws IOException {
     3     
     4     InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
     5     SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     6     
     7     SqlSession session = sessionFactory.openSession();
     8     
     9     try {
    10         EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    11         List<Employee> list = mapper.testConditionIf(new Employee(null, "0", null));
    12         System.out.println(list.size());
    13         for (Employee employee : list) {
    14             System.out.println(list);
    15         }
    16     } catch (Exception e) {
    17         e.printStackTrace();  
    18     } finally {
    19         session.close();
    20     }
    21 }

      4、执行结果

        

    choose

      有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

      示例

      1、EmployeeMapper新增Sql如下:

     1 <!-- choose -->
     2 <select id="testConditionChoose" resultType="com.hd.test.pojo.Employee">
     3     select id, last_name lastName, gender from employee
     4     where 1 = 1
     5     <choose>
     6         <when test="id != null">
     7             AND id = #{id}
     8         </when>
     9         <when test="lastName != null">
    10             AND last_name = #{lastName}
    11         </when>
    12         <when test="gender != null">
    13             AND gender = #{gender}
    14         </when>
    15         <when test="email != null">
    16             AND email = #{email}
    17         </when>
    18         <otherwise>
    19             AND 1 = 1
    20         </otherwise>
    21     </choose>
    22 </select>

      2、EmployeeMapper接口中,新增方法

    1 public List<Employee> testConditionChoose(Employee employee);

       3、测试方法  

     1 @Test
     2 public void test002() throws IOException {
     3     
     4     InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
     5     SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     6     
     7     SqlSession session = sessionFactory.openSession();
     8     
     9     try {
    10         EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    11         List<Employee> list = mapper.testConditionChoose(new Employee(1, null, null, null));
    12         System.out.println(list.size());
    13         for (Employee employee : list) {
    14             System.out.println(list);
    15         }
    16     } catch (Exception e) {
    17         e.printStackTrace();  
    18     } finally {
    19         session.close();
    20     }
    21 }

      4、执行结果

        

    where

      where标签:用于编写带where条件的sql,配合if标签使用,它会自动去除首个AND前缀。

      示例

      1、EmployeeMapper新增Sql如下:

     1 <!-- if + where -->
     2 <select id="testConditionIfWhere"
     3     resultType="com.hd.test.pojo.Employee">
     4     select id, last_name lastName, gender from employee
     5     <where>
     6         <if test="id != null">
     7             AND id = #{id}
     8         </if>
     9         <if test="lastName != null and lastName.trim() != ''">
    10             AND last_name = #{lastName}
    11         </if>
    12         <if test="gender==0 or gender==1">
    13             AND gender = #{gender}
    14         </if>
    15         <if test="email != null &amp;&amp; lastName!=&quot;&quot;">
    16             AND email = #{email}
    17         </if>
    18     </where>
    19 </select>

      2、EmployeeMapper接口中,新增方法

    1 public List<Employee> testConditionIfWhere(Employee employee);

      3、测试方法

     1 @Test
     2 public void test003() throws IOException {
     3     
     4     InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
     5     SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     6     
     7     SqlSession session = sessionFactory.openSession();
     8     
     9     try {
    10         EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    11         List<Employee> list = mapper.testConditionIfWhere(new Employee("小红", "1", null));
    12         System.out.println(list.size());
    13         for (Employee employee : list) {
    14             System.out.println(list);
    15         }
    16     } catch (Exception e) {
    17         e.printStackTrace();  
    18     } finally {
    19         session.close();
    20     }
    21 }

      4、执行结果

        

    trim

      trim标签:可以去掉字符串的首尾字符串,以及在字符串前后添加前后缀

      示例

      1、EmployeeMapper新增Sql如下:

     1 <select id="testConditionIfTrim" resultType="com.hd.test.pojo.Employee">
     2     select id, last_name lastName, gender from employee
     3     <!-- 后面多出的and或者or where标签不能解决 
     4         prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。 prefix给拼串后的整个字符串加一个前缀 
     5         prefixOverrides="": 前缀覆盖: 去掉整个字符串前面多余的字符 
     6         suffix="":后缀 suffix给拼串后的整个字符串加一个后缀 
     7         suffixOverrides="" 后缀覆盖:去掉整个字符串后面多余的字符 -->
     8     <trim prefix="where" prefixOverrides="AND">
     9         <if test="id != null">
    10             AND id = #{id}
    11         </if>
    12         <if test="lastName != null">
    13             AND last_name = #{lastName}
    14         </if>
    15         <if test="gender != null">
    16             AND gender = #{gender}
    17         </if>
    18         <if test="email != null">
    19             AND email = #{email}
    20         </if>
    21     </trim>
    22 </select> 

      2、EmployeeMapper接口中,新增方法

    1 public List<Employee> testConditionIfTrim(Employee employee); 

      3、测试方法

     1 @Test
     2 public void test004() throws IOException {
     3     
     4     InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
     5     SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     6     
     7     SqlSession session = sessionFactory.openSession();
     8     
     9     try {
    10         EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    11         List<Employee> list = mapper.testConditionIfTrim(new Employee(1, null, null, null));
    12         System.out.println(list.size());
    13         for (Employee employee : list) {
    14             System.out.println(list);
    15         }
    16     } catch (Exception e) {
    17         e.printStackTrace();  
    18     } finally {
    19         session.close();
    20     }
    21 }

      4、执行结果

        

        

    foreach

      动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候

      示例

      1、EmployeeMapper新增Sql如下: 

     1 <!-- foreach -->
     2 <select id="testConditionForeach" resultType="com.hd.test.pojo.Employee">
     3     select id, last_name lastName, gender from employee
     4     <!--
     5          collection:指定要遍历的集合:
     6              list类型的参数会特殊处理封装在map中,map的key就叫list
     7          item:将当前遍历出的元素赋值给指定的变量
     8          separator:每个元素之间的分隔符
     9          open:遍历出所有结果拼接一个开始的字符
    10          close:遍历出所有结果拼接一个结束的字符
    11          index:索引。遍历list的时候是index就是索引,item就是当前值
    12                        遍历map的时候index表示的就是map的key,item就是map的值
    13          
    14          #{变量名}就能取出变量的值也就是当前遍历出的元素
    15        -->
    16     <foreach collection="ids" item="id" separator="," open="where id in (" close=")" >
    17         #{id}
    18     </foreach>
    19 </select>

      2、EmployeeMapper接口中,新增方法

    1 public List<Employee> testConditionForeach(@Param("ids")List<Integer> ids);

      3、测试方法

     1 @Test
     2 public void test005() throws IOException {
     3     
     4     InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
     5     SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     6     
     7     SqlSession session = sessionFactory.openSession();
     8     
     9     try {
    10         EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    11         List<Employee> list = mapper.testConditionForeach(Arrays.asList(1, 2, 3, 4));
    12         System.out.println(list.size());
    13         for (Employee employee : list) {
    14             System.out.println(list);
    15         }
    16     } catch (Exception e) {
    17         e.printStackTrace();  
    18     } finally {
    19         session.close();
    20     }
    21

       4、执行结果

        

    set

      set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号

      示例

      1、EmployeeMapper新增Sql如下: 

     1 <!-- set -->
     2 <update id="testConditionSet">
     3     update employee 
     4     <set>
     5         <if test="lastName != null">
     6             last_name = #{lastName},
     7         </if>
     8         <if test="gender != null">
     9             gender = #{gender},
    10         </if>
    11         <if test="email != null">
    12             email = #{email},
    13         </if>
    14     </set>
    15     where id = #{id}
    16 </update> 

      2、EmployeeMapper接口中,新增方法

    1 public boolean testConditionSet(Employee employee);

      3、测试方法 

     1 @Test
     2 public void test006() throws IOException {
     3     
     4     InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
     5     SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     6     
     7     SqlSession session = sessionFactory.openSession();
     8     
     9     try {
    10         EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    11         boolean f = mapper.testConditionSet(new Employee(1, "小白", "1", null));
    12         System.out.println(f);
    13         session.commit();
    14     } catch (Exception e) {
    15         e.printStackTrace();  
    16     } finally {
    17         session.close();
    18     }
    19 }

      4、执行结果

        

    bind

      bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:

    1 <select id="testConditionBind" resultType="Blog">
    2     <bind name="pattern" value="'%' + keyword + '%'" />
    3     SELECT * FROM employee  WHERE last_name LIKE #{pattern}
    4 </select>

    sql

      可以用来包含其他sql

    1 <sql id="selectSql">select id, last_name lastName, gender from employee</sql>
    2     
    3 <select id="testConditionInclude" resultType="com.hd.test.pojo.Employee">
    4     <include refid="selectSql"></include>
    5     where id = 1
    6 </select>

     Mybatis中2个内置参数 _parameter和_databaseId

      示例

      1、EmployeeMapper新增Sql如下:

     1 <!-- 两个内置参数:
     2      不只是方法传递过来的参数可以被用来判断,取值。。。
     3      mybatis默认还有两个内置参数:
     4      _parameter:代表整个参数
     5          单个参数:_parameter就是这个参数
     6          多个参数:参数会被封装为一个map;_parameter就是代表这个map
     7      
     8      _databaseId:
     9          如果配置了databaseIdProvider标签。 _databaseId就是代表当前数据库的别名mysql
    10          如果没配置了databaseIdProvider标签。 _databaseId为null
    11   -->
    12 <select id="testInnerParameter" resultType="com.hd.test.pojo.Employee">
    13     <if test="_databaseId == 'mysql'">select * from ${_parameter}</if>
    14     <if test="_databaseId != 'mysql'">select * from ${_parameter} where 1 = 1</if>
    15 </select>

      2、mybatis-config.xml中的配置

    1 <databaseIdProvider type="DB_VENDOR">
    2     <!-- 为不同的数据库厂商起别名 -->
    3     <property name="MySQL" value="mysql"/>
    4     <property name="Oracle" value="oracle"/>
    5     <property name="SQL Server" value="sqlserver"/>
    6 </databaseIdProvider>

       3、EmployeeMapper接口中,新增方法 

    1 public List<Employee> testInnerParameter(String tableName);

      4、测试方法 

     1 @Test
     2 public void test007() throws IOException {
     3     
     4     InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
     5     SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     6     
     7     SqlSession session = sessionFactory.openSession();
     8     
     9     try {
    10         EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    11         List<Employee> list = mapper.testInnerParameter("employee");
    12         System.out.println(list.size());
    13         for (Employee employee : list) {
    14             System.out.println(employee);
    15         }
    16         
    17     } catch (Exception e) {
    18         e.printStackTrace();  
    19     } finally {
    20         session.close();
    21     }
    22 }

      5、执行结果,从执行结果可以看出,_parameter == employee 参数,_databaseId == mysql 数据库别名

        

  • 相关阅读:
    [转]使用NLog记录日志到数据库 自定义日志表的数据格式
    [转]使用C#实现长整型向任意编码的转换和逆转换
    解释一下 P/NP/NPComplete/NPHard 等问题
    在C#中创建进度窗体
    [转载] 关于Winform编译中的属性设置
    [转]使用NLog記錄Exception
    SQL Server数据库,在表上建立唯一性索引的一些问题
    DES文件字符加密解密
    线程运行超时处理类
    使用FFmpeg从视频中截图的命令
  • 原文地址:https://www.cnblogs.com/h--d/p/10326766.html
Copyright © 2011-2022 走看看