zoukankan      html  css  js  c++  java
  • MyBatis知多少(25)动态SQL

    使用动态查询是MyBatis一个非常强大的功能。有时你已经改变WHERE子句条件的基础上你的参数对象的状态。在这种情况下的MyBatis提供了一组可以映射语句中使用,以提高SQL语句的重用性和灵活性的动态SQL标签。

    所有的逻辑是使用一些额外的标签放在:XML文件。下面是一个例子,其中的SELECT语句将努力在两个方面:

    • 如果想传递一个ID,然后它会返回所有与该ID的记录,

    • 否则,将返回所有雇员ID为NULL的记录。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE sqlMap 
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">
    
    <sqlMap namespace="Employee">
    <select id="findByID" resultClass="Employee">
       SELECT * FROM EMPLOYEE
       <dynamic prepend="WHERE ">
          <isNull property="id">
             id IS NULL
          </isNull>
          <isNotNull property="id">
             id = #id#
          </isNotNull>
       </dynamic>
    </select>
    </sqlMap>

    可以使用<isNotEmpty>标签如下检查条件。在此条件下将增加,只有当通过属性不为空。

    ..................
    <select id="findByID" resultClass="Employee">
       SELECT * FROM EMPLOYEE
       <dynamic prepend="WHERE ">
          <isNotEmpty property="id">
               id = #id#
          </isNotEmpty>
       </dynamic>
    </select>
    ..................

    如果想查询对id和/或雇员的名字选取。SELECT语句如下:

    ..................
    <select id="findByID" resultClass="Employee">
       SELECT * FROM EMPLOYEE
       <dynamic prepend="WHERE ">
          <isNotEmpty prepend="AND" property="id">
               id = #id#
          </isNotEmpty>
          <isNotEmpty prepend="OR" property="first_name">
               first_name = #first_name#
          </isNotEmpty>
       </dynamic>
    </select>
    ..................

    例如:动态SQL

    下面的例子将展示如何编写SELECT语句中使用动态SQL。考虑,我们已经在MySQL下有EMPLOYEE表:

    CREATE TABLE EMPLOYEE (
       id INT NOT NULL auto_increment,
       first_name VARCHAR(20) default NULL,
       last_name  VARCHAR(20) default NULL,
       salary     INT  default NULL,
       PRIMARY KEY (id)
    );

    此表有如下只有一条记录:

    mysql> select * from EMPLOYEE;
    +----+------------+-----------+--------+
    | id | first_name | last_name | salary |
    +----+------------+-----------+--------+
    |  1 | Zara       | Ali       |   5000 |
    |  2 | Roma       | Ali       |   3000 |
    |  3 | Noha       | Ali       |   7000 |
    +----+------------+-----------+--------+
    3 row in set (0.00 sec)

    Employee POJO 类:

    要执行读取操作,让我们在Employee.java文件Employee类,如下所示:

    public class Employee {
      private int id;
      private String first_name; 
      private String last_name;   
      private int salary;  
    
      /* Define constructors for the Employee class. */
      public Employee() {}
      
      public Employee(String fname, String lname, int salary) {
        this.first_name = fname;
        this.last_name = lname;
        this.salary = salary;
      }
    
      /* Here are the method definitions */
      public int getId() {
        return id;
      }
      public String getFirstName() {
        return first_name;
      }
      public String getLastName() {
        return last_name;
      }
      public int getSalary() {
        return salary;
      }
    } /* End of Employee */

    Employee.xml 文件:

    要定义使用iBATIS SQL映射语句,我们将增加在以下文件Employee.xml修改<select>标记和这个标签定义,我们将定义一个“id”,这将被用于IbatisReadDy.java文件上执行动态SQL的SELECT查询数据库。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE sqlMap 
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">
    
    <sqlMap namespace="Employee">
    <select id="findByID" resultClass="Employee">
       SELECT * FROM EMPLOYEE
       <dynamic prepend="WHERE ">
          <isNotNull property="id">
             id = #id#
          </isNotNull>
       </dynamic>
    </select>
    </sqlMap>

    上面的SELECT语句将努力在两个方面(一)如果想传递一个ID,然后将相应的编号(二)返回的记录,否则将返回所有记录。

    IbatisReadDy.java 文件:

    文件将应用程序级别的逻辑从Employee表读出的条件记录:

    import com.ibatis.common.resources.Resources;
    import com.ibatis.sqlmap.client.SqlMapClient;
    import com.ibatis.sqlmap.client.SqlMapClientBuilder;
    import java.io.*;
    import java.sql.SQLException;
    import java.util.*;
    
    public class IbatisReadDy{
      public static void main(String[] args)
       throws IOException,SQLException{
       Reader rd=Resources.getResourceAsReader("SqlMapConfig.xml");
       SqlMapClient smc=SqlMapClientBuilder.buildSqlMapClient(rd);
    
       /* This would read all records from the Employee table.*/
       System.out.println("Going to read records.....");
       Employee rec = new Employee();
       rec.setId(1);
    
       List <Employee> ems = (List<Employee>)
                       smc.queryForList("Employee.findByID", rec);
       Employee em = null;
       for (Employee e : ems) {
          System.out.print("  " + e.getId());
          System.out.print("  " + e.getFirstName());
          System.out.print("  " + e.getLastName());
          System.out.print("  " + e.getSalary());
          em = e; 
          System.out.println("");
       }    
    
       System.out.println("Records Read Successfully ");
    
      }
    }

    编译和运行:

    下面是步骤来编译并运行上述应用。请确保已在进行的编译和执行之前,适当地设置PATH和CLASSPATH。

    • 创建Employee.xml如上所示。

    • 创建Employee.java如上图所示,并编译它。

    • 创建IbatisReadDy.java如上图所示,并编译它。

    • 执行IbatisReadDy二进制文件来运行程序。

    会得到下面的结果,并且将记录从EMPLOYEE表中读取。

    Going to read records.....
      1  Zara  Ali  5000
    Record Reads Successfully

    试试上面的例子中通过传递空值作为smc.queryForList(“Employee.findByID”,NULL)。

    iBATIS OGNL 表达式

    iBATIS的提供了强大的基于OGNL的表达式来消除其他元素。

    • if 语句

    • choose, when, otherwise 语句

    • where 语句

    • foreach 语句

    if语句:

    最常见的事情在动态SQL是有条件地包括一个where子句的一部分。例如:

    <select id="findActiveBlogWithTitleLike"
               parameterType="Blog" resultType="Blog">
       SELECT * FROM BLOG
       WHERE state = 'ACTIVE.
       <if test="title != null">
          AND title like #{title}
       </if>
    </select>

    这条语句会提供功能的可选的文本搜索类型。如果没有传递title,那么所有激活的博客将被退回。但是,如果传递一个标题,它会寻找标题以like 给定的条件。 

    可以包括多个if条件如下:

    最常见的事情在动态SQL是有条件地包括一个where子句的一部分。例如:

    <select id="findActiveBlogWithTitleLike"
               parameterType="Blog" resultType="Blog">
       SELECT * FROM BLOG
       WHERE state = 'ACTIVE.
       <if test="title != null">
          AND title like #{title}
       </if>
       <if test="author != null">
          AND author like #{author}
       </if>
    </select>

    choose, when, otherwise 语句:

    iBATIS提供了一个选择的元素,它类似于Java的switch语句。这有助于选择很多种情况。

    下面的例子将只搜索标题上如果提供,那么只有由作者如果已提供。如果没有提供,让我们只返回精选的博客:

    <select id="findActiveBlogWithTitleLike"
               parameterType="Blog" resultType="Blog">
       SELECT * FROM BLOG
       WHERE state = 'ACTIVE.
       <choose>
          <when test="title != null">
             AND title like #{title}
          </when>
          <when test="author != null and author.name != null">
             AND author like #{author}
          </when>
          <otherwise>
             AND featured = 1
          </otherwise>
       </choose>
    </select>

    where 语句:

    如果我们看一下前面的例子中,如果没有一个条件满足会发生什么事?最终SQL看起来像这样:

    SELECT * FROM BLOG
    WHERE

    这会失败,但iBATIS有一个简单的改变一个简单的解决方案,让一切工作正常:

     <select id="findActiveBlogLike"
               parameterType="Blog" resultType="Blog">
       SELECT * FROM BLOG
       <where>
          <if test="state != null">
             state = #{state}
          </if>
          <if test="title != null">
             AND title like #{title}
          </if>
          <if test="author != null>
             AND author like #{author}
          </if>
       </where>
    </select>

    where元素知道只有插入WHERE ,如果有一个由含标签返回的任何内容。此外,如果该内容开头AND或OR,它知道剥离其关闭。

    foreach语句:

    foreach元素是非常强大的,并允许你指定一个集合,声明可以在元素的体内可用于项目和索引变量。

    它也允许你指定打开和关闭的字符串,并添加一个分隔符放置在迭代之间。可以建立一个IN条件如下:

    <select id="selectPostIn" resultType="domain.blog.Post">
       SELECT *
       FROM POST P
       WHERE ID in
       <foreach item="item" index="index" collection="list"
          open="(" separator="," close=")">
             #{item}
       </foreach>
    </select>

    系列文章:

    MyBatis知多少(1)

    MyBatis知多少(2)

    MyBatis知多少(3)

    MyBatis知多少(4)MyBatis的优势

    MyBatis知多少(5)业务对象模型

    MyBatis知多少(6)表现层与业务逻辑层

    MyBatis知多少(7)持久层

    MyBatis知多少(8)关系型数据库

    MyBatis知多少(9)不同类型的数据库

    MyBatis知多少(10)应用程序数据库

    MyBatis知多少(11)企业数据库

    MyBatis知多少(12)私有数据库

    MyBatis知多少(13)MyBatis如何解决数据库的常见问题

    MyBatis知多少(14)分散的数据库系统

    MyBatis知多少(15)数据模型

    MyBatis知多少(16)MyBatis映射

    MyBatis知多少(17)MyBatis和JDBC

    MyBatis知多少(18)MyBatis系统

    MyBatis知多少(19)MyBatis操作

    MyBatis知多少(20)MyBatis读取操作

    MyBatis知多少(21)更新操作

    MyBatis知多少(22)MyBatis删除操作

    MyBatis知多少(23)MyBatis结果映射

    MyBatis知多少(24)存储过程

    
    
  • 相关阅读:
    poj 1014||hdu 1059 dividing(多重背包 二进制优化)
    Java多线程循环打印ABC的5种实现方法
    java资料搜索网站
    idea 离线安装 lombok插件
    解决TIME_WAIT过多造成的问题
    JAVA线程池详解
    linux vmstat命令
    Mysql慢查询
    sql中强制使用索引
    JAVA 利用 jmc或jvisualvm 监控 本地或者远程JVM
  • 原文地址:https://www.cnblogs.com/Coda/p/4694796.html
Copyright © 2011-2022 走看看