Java的MyBatis框架中对数据库进行动态SQL查询的教程_java

其实MyBatis具有的一个强大的特性之一通常是它的动态 SQL 能力。 如果你有使用 JDBC 或其他 相似框架的经验,你就明白要动态的串联 SQL 字符串在一起是十分纠结的,确保不能忘了空格或在列表的最后省略逗号。Mybatis中的动态 SQL 可以彻底处理这种痛苦。对于动态SQL,最通俗简单的方法就是我们自己在硬编码的时候赋予各种动态行为的判断,而在Mybatis中,用一种强大的动态 SQL 语 言来改进这种情形,这种语言可以被用在任意映射的 SQL 语句中。动态 SQL 元素和使用 JSTL 或其他相似的基于 XML 的文本处理器相似。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。
我们常用的几个节点元素有if,choose(when, otherwise),trim(where, if),foreach。真正使用下来我感觉有点像XSLT(文章后面会顺带提一下~)的用法。
(1)if 的用法

在ViisitMapper的分页配置中,如果pageIndex>-1 and pageSize>-1的时候就加入相应的分页SQL,否则就不添加(默认取全部),如下:

<select id="getListByPagenate" parameterType="PagenateArgs"
  resultType="Visitor">
  select * from (
  <include refid="getListSql" /> <include refid="orderBySql"/>
  ) t <!-- #{}表示参数化输出,${}表示直接输出不进行任何转义操作,自己进行转移 -->
  <if test="pageStart>-1 and pageSize>-1">
    limit #{pageStart}, #{pageSize}
  </if>
</select>
<sql id="getListSql">
  select * from Visitor where
  status>0
</sql>
<sql id="orderBySql">
  order by ${orderFieldStr} ${orderDirectionStr}
</sql>

  因为我们的参数pageIndex与pageSize都是int值所以可以这样直接判断,如果是对象实例我们可以利用null判断来进行一些动态逻辑的控制,具体实际开发中就要看业务需求了。这里我认为要注意的是别十分顺手的吧and写成&&,这个在配置中不会被识别~。

(2)choose (when, otherwise)的用法

  choose when 主要在多个条件的情况下只满足其中一个条件的应用场景中使用,例如这里就构建一个query条件,分别传递id,name与createTime。假设我们查询Visitor表时,如果VisitorId有值则,使用Id查询,如果VisitorName有值则采用VisitName查询,如下,还是在david.mybatis.demo.IVisitorOperation接口类中添加List<Visitor> getListChooseWhenDemo(BasicQueryArgs args)方法。在VisitorMapper中添加相应的的select节点配置:

package david.mybatis.demo;

import java.util.List;

import david.mybatis.model.BasicQueryArgs;
import david.mybatis.model.PagenateArgs;
import david.mybatis.model.Visitor;
import david.mybatis.model.VisitorWithRn;

public interface IVisitorOperation {
  /*
   * 添加访问者
   */
  public int add(Visitor visitor);

  /*
   * 删除访问者
   */
  public int delete(int id);

  /*
   * 更新访问者
   */
  public int update(Visitor visitor);

  /*
   * 查询访问者
   */
  public Visitor query(int id);

  /*
   * 查询List
   */
  public List<Visitor> getList();

  /*
   * 分页查询List
   */
  public List<Visitor> getListByPagenate(PagenateArgs args);

  /*
   * 分页查询List(包含Rownum)
   */
  public List<VisitorWithRn> getListByPagenateWithRn(PagenateArgs args);

  /*
   * 基础查询
   */
  public Visitor basicQuery(int id);

  /*
   * 动态条件查询(choose,when)实例
   */
  public List<Visitor> getListChooseWhenDemo(BasicQueryArgs args);

  /*
   * 动态条件查询(where,if)实例
   */
  public List<Visitor> getListWhereDemo(BasicQueryArgs args);

  /*
   * 动态查询(foreach)实例
   */
  public List<Visitor> getListForeachDemo(List<Integer> ids);

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="david.mybatis.demo.IVisitorOperation">
  <resultMap type="Visitor" id="visitorRs">
    <id column="Id" property="id" />
    <result column="Name" property="name" />
    <result column="Email" property="email" />
    <result column="Status" property="status" />
    <result column="CreateTime" property="createTime" />
  </resultMap>
  <sql id="getListSqlConditions">
    select * from Visitor
  </sql>
  <!-- 满足其中一个条件时候用choose when操作 -->
  <select id="getListChooseWhenDemo" resultMap="visitorRs"
    parameterType="BasicQueryArgs">
    <include refid="getListSqlConditions" />
    <where>
      <if test="queryStatus>0">
        status=#{queryStatus}
      </if>
      <choose>
        <when test="queryId!=0">
          and id=#{queryId}
        </when>
        <when test="queryName!=null">
          and name like #{queryName}
        </when>
        <otherwise>
          and createTime>= #{queryTime}
        </otherwise>
      </choose>
    </where>
  </select>
</mapper>

(3)where if (trim)的用法

where关键词的好处是在于,如果有相应的过滤条件的话,它知道在适当的时候插入where关键词。而且它也知道在何时该去掉相应的AND与OR的连接符,主要应对如下情景

<select id="findActiveBlogLike"
   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.name != null">
  AND author_name like #{author.name}
 </if>
</select>

不会因为所有条件不满足变为

<select id="findActiveBlogLike"
   resultType="Blog">
 SELECT * FROM BLOG
 WHERE
</select>

或者因为没有满足第一个条件,单单满足后面的条件变成

<select id="findActiveBlogLike"
   resultType="Blog">
  SELECT * FROM BLOG
  WHERE
  AND title like ‘someTitle'
</select>

所以针对这种我们可以在建立choose when条件示例,同样在IVisitorOperation接口类中加入相应的方法public List<Visitor> getListWhereDemo(BasicQueryArgs args),把VisitorMapper配置文件中的相对应配置加上去如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="david.mybatis.demo.IVisitorOperation">
  <sql id="getListSqlConditions">
    select * from Visitor
  </sql>
  <!-- 满足条件的都加上去操作 -->
  <select id="getListWhereDemo" resultMap="visitorRs"
    parameterType="BasicQueryArgs">
    <include refid="getListSqlConditions" />

    <where>
      <if test="queryStatus>0">
        status>0
      </if>
      <if test="queryId>0">
        and id=#{queryId}
      </if>
      <if test="queryName!=null">
        and name like=#{queryName}
      </if>
      <if test="queryTime!=null">
        and createTime>=#{queryTime}
      </if>
    </where>
    <!--
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
      <if test="queryStatus>0">
        status>0
      </if>
      <if test="queryId>0">
        and id=#{queryId}
      </if>
      <if test="queryName!=null">
        and name like=#{queryName}
      </if>
      <if test="queryTime!=null">
        and createTime>=#{queryTime}
      </if>
    </trim>
    -->
  </select>
</mapper>

(4)foreach的用法

在常用的动态SQL中我们有个业务场景是要where id in 一大串的ID,像这种情况我们就可以用到foreach啦,不必自己辛辛苦苦去拼接Id字符串啦。同样的步骤还是在IVisitorOperation接口类中加入相应的方法public List<Visitor> getListForeachDemo(List<Integer> ids),然后再对应的Mapper文件中配置上相应的节点元素信息,如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="david.mybatis.demo.IVisitorOperation">
  <sql id="getListSqlConditions">
    select * from Visitor
  </sql>
  <!-- Foreach循环条件 -->
  <select id="getListForeachDemo" resultMap="visitorRs">
    <include refid="getListSqlConditions"/>
    where status>0 and id in
    <foreach collection="list" item="item" index="index" open="(" separator="," close=")">
      ${item}
    </foreach>
  </select>
</mapper>

最后你只需要在DemoRun中建立相应的测试方法,Mybatis里面的动态SQL也就完成啦,下面测试用的DemoRun方法

/*
   * 动态查询foreach实例
   */
  public static void getListForeachDemo(List<Integer> ids) {
    SqlSession session = MybatisUtils.getSqlSession();
    IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
    List<Visitor> ls = vOperation.getListForeachDemo(ids);
    for (Visitor visitor : ls) {
      System.out.println(visitor);
    }
  }

  /*
   * 动态查询where if实例
   */
  public static void getListWhereCondition(int id, String name, Date createTime) {
    name = name == "" ? null : name;
    SqlSession session = MybatisUtils.getSqlSession();
    BasicQueryArgs args = new BasicQueryArgs(id, name, createTime);
    IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
    List<Visitor> ls = vOperation.getListWhereDemo(args);
    if (ls.size() == 0)
      System.out.println("查无匹配!");
    else {
      for (Visitor visitor : ls) {
        System.out.println(visitor);
      }
    }
  }

  /*
   * 动态查询choose when实例
   */
  public static void getListChooseWhenDemo(int id, String name, Date createTime) {
    name = name == "" ? null : name;
    SqlSession session = MybatisUtils.getSqlSession();
    BasicQueryArgs args = new BasicQueryArgs(id, name, createTime);
    IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
    List<Visitor> ls = vOperation.getListChooseWhenDemo(args);
    if (ls.size() == 0)
      System.out.println("查无匹配!");
    else {
      for (Visitor visitor : ls) {
        System.out.println(visitor);
      }
    }
  }

   
PS:关于OGNL
OGNL 是 Object-Graph Navigation Language 的缩写,从语言角度来说:它是一个功能强大的表达式语言,用来获取和设置 java 对象的属性 , 它旨在提供一个更高抽象度语法来对 java 对象图进行导航,OGNL 在许多的地方都有应用,例如:
作为 GUI 元素(textfield,combobox, 等)到模型对象的绑定语言。
数据库表到 Swing 的 TableModel 的数据源语言。
web 组件和后台 Model 对象的绑定语言 (WebOGNL,Tapestry,WebWork,WebObjects) 。
作为 Jakarata Commons BeanUtils 或者 JSTL 的表达式语言的一个更具表达力的替代语言。
另外,java 中很多可以做的事情,也可以使用 OGNL 来完成,例如:列表映射和选择。 对于开发者来说,使用 OGNL,可以用简洁的语法来完成对 java 对象的导航。通常来说: 通过一个“路径”来完成对象信息的导航,这个“路径”可以是到 java bean 的某个属性,或者集合中的某个索引的对象,等等,而不是直接使用 get 或者 set 方法来完成。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, sql
, mybatis
查询
mybatis 动态数据库名、mybatis 动态数据库、java框架mybatis、java数据库框架、java数据库操作框架,以便于您获取更多的相关知识。

时间: 2024-08-04 03:52:07

Java的MyBatis框架中对数据库进行动态SQL查询的教程_java的相关文章

整理Java的MyBatis框架中一些重要的功能及基本使用示例_java

基本用法回顾:SQL语句存储在XML文件或Java 注解中.一个MaBatis映射的示例(其中用到了Java接口和MyBatis注解): package org.mybatis.example; public interface BlogMapper { @Select("select * from Blog where id = #{id}") Blog selectBlog(int id); } 执行的示例: BlogMapper mapper = session.getMappe

Java的Spring框架中AOP项目的一般配置和部署教程_java

0.关于AOP面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也是Spring框架中的一个重要内容.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. AOP是OOP的延续. 主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等. 主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对

详解Java的Hibernate框架中的缓存与原生SQL语句的使用_java

Hibernate缓存缓存是所有关于应用程序的性能优化和它位于应用程序和数据库之间,以避免数据库访问多次,让性能关键型应用程序有更好的表现. 缓存对Hibernate很重要,它采用了多级缓存方案下文所述: 第一级缓存: 第一级缓存是Session的缓存,是一个强制性的缓存,通过它所有的请求都必须通过. Session对象不断自身的动力的对象,提交到数据库之前. 如果发出多个更新一个对象,Hibernate试图拖延尽可能长的时间做了更新,以减少发出的更新SQL语句的数量.如果您关闭会话,所有被缓存

Java的MyBatis框架中Mapper映射配置的使用及原理解析_java

Mapper的内置方法model层就是实体类,对应数据库的表.controller层是Servlet,主要是负责业务模块流程的控制,调用service接口的方法,在struts2就是Action.Service层主要做逻辑判断,Dao层是数据访问层,与数据库进行对接.至于Mapper是mybtis框架的映射用到,mapper映射文件在dao层用. 下面是介绍一下Mapper的内置方法: 1.countByExample ===>根据条件查询数量 int countByExample(UserEx

Java的MyBatis框架中XML映射缓存的使用教程_java

MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.默认情况下是没有开启缓存的,要开启二级缓存,你需要在你的SQL映射文件中添加一行: <cache/> 字面上看就是这样.这个简单语句的效果如下: 1.映射语句文件中的所有select语句将会被缓存. 2.映射语句文件中的所有insert,update和delete语句会刷新缓存. 3.缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回. 4.根据时间表(比如 no Flush Inter

Java的MyBatis框架中MyBatis Generator代码生成器的用法_java

关于Mybatis GeneratorMyBatis Generator (MBG) 是一个Mybatis的代码生成器 MyBatis 和 iBATIS. 他可以生成Mybatis各个版本的代码,和iBATIS 2.2.0版本以后的代码. 他可以内省数据库的表(或多个表)然后生成可以用来访问(多个)表的基础对象. 这样和数据库表进行交互时不需要创建对象和配置文件. MBG的解决了对数据库操作有最大影响的一些简单的CRUD(插入,查询,更新,删除)操作. 您仍然需要对联合查询和存储过程手写SQL和

详解Java的MyBatis框架中的缓存与缓存的使用改进_java

一级缓存与二级缓存MyBatis将数据缓存设计成两级结构,分为一级缓存.二级缓存: 一级缓存是Session会话级别的缓存,位于表示一次数据库会话的SqlSession对象之中,又被称之为本地缓存.一级缓存是MyBatis内部实现的一个特性,用户不能配置,默认情况下自动支持的缓存,用户没有定制它的权利(不过这也不是绝对的,可以通过开发插件对它进行修改): 二级缓存是Application应用级别的缓存,它的是生命周期很长,跟Application的声明周期一样,也就是说它的作用范围是整个Appl

在Java的Hibernate框架中对数据库数据进行查询操作_java

Hibernate查询语言(HQL)是一种面向对象的查询语言,类似于SQL,但不是对表和列操作,HQL适用于持久对象和它们的属性. HQL查询由Hibernate转换成传统的SQL查询,这在圈上的数据库执行操作. 虽然可以直接使用SQL语句和Hibernate使用原生SQL,但建议使用HQL尽可能避免数据库可移植性的麻烦,并采取Hibernate的SQL生成和缓存策略的优势. 都像SELECT,FROM和WHERE等关键字不区分大小写,但如表名和列名的属性是区分在HQL敏感. FROM 语句使用

《Java EE核心框架实战》—— 2.6 动态SQL的使用

2.6 动态SQL的使用 MyBatis框架还支持动态SQL标签的使用,而且某些标签的使用率还非常高. 2.6.1插入null值时的处理第1种方法-jdbcType 创建名为dynSqlTest的Web项目,创建名为test1的Servlet对象,核心代码如下. public class test1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) t