Mybatis如何使用ognl表达式实现动态sql

本文讲述在mybatis中如何使用ognl表达式实现动态组装sql语句

新建Users实体类:

public class Users {
    private Integer uid;
    private String userName;
    private String tel;
    //添加上面私有字段的get、set方法
}

新建一个Dao接口类,mybatis配置文件在配置namespace属性时需要加入这个类的完整类名,找到这个类里的方法执行:

public interface UserDao {
    /**
     * 依据userName查询用户信息
     * @param user
     * @return
     */
    List<Users> listUser(Users user);
    /**
     * 动态选择条件
     * @param user
     * @return
     */
    List<Users> listUser2(Users user);
    /**
     * 动态范围查询
     * @param uids
     * @return
     */
    List<Users> listUser3(Integer[] uids);
    /**
     * 动态更新用户信息
     * @param user
     */
    void updateUser(Users user);
    /**
     * 批量添加
     * @param list
     */
    void addBatch(List<Users> list);
    /**
     * 批量删除
     * @param ids
     */
    void deleteBatch(int[] ids);
    /**
     * 批量更新
     * @param list
     */
    void updateBatch1(List<Users> list);
    /**
     * 批量更新
     * @param list
     */
    void updateBatch2(List<Users> list);
}

新建mybatis的配置文件(下面代码可以作为mybatis配置文件的模板,这里的namespace属性可以设置为上面的dao类的完整类名):

<?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指定Dao接口的完整类名,
因为mybatis在解析的时候要根据这个类名找到相应dao方法执行 --><mapper namespace="">   </mapper>

在mybatis配置文件中写一条条件查询sql语句:

<!-- 动态查询(使用if拼接条件,适用于多选多的形式) -->
<select id="listUser" parameterType="users" resultMap="userMap">
    select u_id, u_name, u_tel from user_info4 user_info
    <where>
        <if test="userName != null and userName !=''">
            u_name = #{userName}
        </if>
        <if test="tel != null and tel !=''">
            and u_tel = #{tel}
        </if>
    </where>
</select>

这里使用了where和if标签,<where></where>意思就是sql语句中的where,当然,where直接在sql中写出来也可以,<if></if>标签就是条件判断,test属性中写条件语句,如果test中的条件语句为true,那么标签中的sql语句就会拼接到上面的sql语句中,所以这条sql语句的意思就是如果传过来的Users对象中,userName字段不为null,或字段值不为空,那么就添加一个对userName的查询,tel也是如此。

注意:在对tel字段的判断时,标签中的sql语句前加了一个and,如果前一条判断为false,那么mybatis会自动将and关键字删除。

<!-- 动态查询(使用choose选择条件,适用于多选一) -->
<select id="listUser2" parameterType="users" resultMap="userMap">
    select u_id, u_name, u_tel from user_info4
    <choose>
        <when test="userName != null and userName != ''">
            where u_name = #{userName}
        </when>
        <when test="tel != null and tel != ''">
            where u_tel = #{tel}
        </when>
        <otherwise>
            order by u_id desc
        </otherwise>
    </choose>
</select>

这里使用的是choose-when-otherwise标签,有点类似于java中的switch-case-default选择条件语句,相比于if标签,这里只能选择一个,即多选一。

在这条sql语句中,会按顺序判断when子句,如果所有的when子句都为false,则会执行otherwise子句中的sql语句。

<!-- 动态查询(使用foreach范围查询,适用于in和or语句) -->
<!-- int[] ids = new int[]{1,2,3,4}; -->
<select id="listUser3" parameterType="collection" resultMap="userMap">
    select u_id, u_name, u_tel from user_info4
    <where>
        u_id in
        <if test="array != null">
            <foreach collection="array" item="id" open="(" separator="," close=")">
                #{id}
            </foreach>
        </if>
    </where>
</select>

foreach标签适用于范围查询(in和or语句),如遍历一个id集合,查询出集合中所有id对应的用户。在foreach标签中,collection属性指定需要遍历的集合的名称,这里只有一个参数,所以可以随意取;item指定遍历的每一项的别名,open指定在遍历前需要加上的内容,separator指定每遍历一个后加上的内容,close指定遍历完后需要加上的内容,如遍历上面的ids集合,那么最终得到的内容就是 (1,2,3,4) 。

<!-- 动态更新(使用set动态更新字段) -->
<update id="updateUser" parameterType="users" >
    update user_info4
    <trim prefix="set" suffixOverrides=",">
        <if test="userName != null and userName != ''">
            u_name = #{userName},
        </if>
        <if test="tel != null and tel != ''">
            u_tel = #{tel}
        </if>
    </trim>
    <!-- where u_id = #{uid} -->
    <where>
        u_id = #{uid}
    </where>
</update>

trim标签用于动态设值,例如在更新数据时,可以动态将改变的字段设置。在trim标签中,prefix属性表示在更新字段之前添加set关键字,suffixOverrides表示将最后一个更新字段的逗号替换成suffix指定的空格符,如果不指定suffix默认就是空格。

<!-- 批量添加,利用sql的特性 -->
<insert id="addBatch" parameterType="list">
    insert into user_info4(u_id, u_name, u_tel) values
    <foreach collection="list" item="user" separator=",">
        (#{user.uid}, #{user.userName}, #{user.tel})
    </foreach>
</insert>

foreach标签不仅可以用于范围查询,还可以遍历集合用于批量添加。

因为可以利用sql的特性,例如:insert into user_info4(u_name, u_tel) values('', ''), ('', ''), ('', '');这样执行这条sql语句就可以实现批量添加。

<!-- 批量更新1,这一种方式兼容性较好,当数据量大时 -->
<update id="updateBatch1" parameterType="list">
    <foreach collection="list" item="user" separator=";">
        update user_info4
        <set>
            u_name = #{user.userName}
        </set>
        where u_id = #{user.uid}
    </foreach>
</update>

foreach还可以用于遍历出多条sql语句,使得一次可以执行多条sql,当然,如果需要MySql执行多条批量操作时,需要开启批量查询功能,即在MySql的url中加入 allowMultiQueries=true 。

<!-- 批量更新2,使用MySQL的case when语句 -->
    <update id="updateBatch2" parameterType="list">
        update user_info4 set u_name = case u_id
        <foreach collection="list" item="user" separator=" ">
            when #{user.uid} then #{user.userName}
        </foreach>
        end
        where u_id in
        <foreach collection="list" item="user" open="(" close=")" separator=",">
            #{user.uid}
        </foreach>
    </update>

这里使用的是MySql中的case when语句来更新的,基本语法:

update user_info4 set u_name = case u_id
  when 3 then '游客1'
  when 4 then '游客2'
  end
  where u_id in(3,4);

Mybatis中的ognl使用总结

经常在写mapper中用到一些OGNL,但是没怎么总结,使用方法一直模模糊糊的。抽点时间,查了别人的blog,做个简单的总结

1.概念

OGNL,Object Graph Navigation Language,是一种强大的表达式语言,网上搜索这个概念,多是和structs有关的。但是在mybatis中OGNL应用很广的;

2.基本参数

Mybatis中常用的OGNL表达式有以下:

e1 or e2

e1 and e2

e1 == e2,e1 eq e2

e1 != e2,e1 neq e2

e1 lt e2:小于

e1 lte e2:小于等于,其他gt(大于),gte(大于等于)

e1 in e2

e1 not in e2

e1 + e2,e1 * e2,e1/e2,e1 - e2,e1%e2

!e,not e:非,求反

e.method(args)调用对象方法

e.property对象属性值

e1[ e2 ]按索引取值,List,数组和Map

@class@method(args)调用类的静态方法

@class@field调用类的静态字段值

更加详细的介绍可以参考官网的介绍:https://commons.apache.org/proper/commons-ognl/language-guide.html

在一定意义上说,mybatis中的动态sql也是基于OGNL表达式的。其中常用的元素有如下几种:

    if
    choose(when,otherwise)
    trim
    where
    set
    foreach

3.应用;

OGNL在mybatis中的应用,主要有两种;

1)动态SQL表达式;

举个栗子:

<code class="language-xml hljs  has-numbering"><span class="hljs-tag"><<span class="hljs-title">select</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"demo1"</span> <span class="hljs-attribute">...</span>></span>
</code><pre name="code" class="prettyprint"><code class="language-xml hljs  has-numbering">    select id, name from users
    <span class="hljs-tag"><<span class="hljs-title">bind</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"nameLike"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"'%' + name + '%'"</span>/></span>
    <span class="hljs-tag"><<span class="hljs-title">where</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">if</span> <span class="hljs-attribute">test</span>=<span class="hljs-value">"name != null and name != ''"</span>></span>
            name like '${nameLike}'
        <span class="hljs-tag"></<span class="hljs-title">if</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">where</span>></span>
<span class="hljs-tag"></<span class="hljs-title">select</span>></span></code>

其中的bind中的value值会使用OGNL计算,ps,其中bind的参数调用只能用$获取;

2)${param}参数中

<code class="language-xml hljs  has-numbering"><span class="hljs-tag"><<span class="hljs-title">select</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"demo2"</span> <span class="hljs-attribute">...</span>></span>
    select id,name from users
    <span class="hljs-tag"><<span class="hljs-title">where</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">if</span> <span class="hljs-attribute">test</span>=<span class="hljs-value">"name != null and name != ''"</span>></span>
            name like '${'%' + name + '%'}'
        <span class="hljs-tag"></<span class="hljs-title">if</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">where</span>></span>
<span class="hljs-tag"></<span class="hljs-title">select</span>></span></code>

此处写的是 ${'%' + name + '%'},而不是 %${name}%,这两种方式的结果一样,但是处理过程不一样。

ps,说明一下#和$的区别:${} 为原样输出,你传什么,sql里就填入什么,比如有引号它也会原样填到sql里。#{} 会使用 PreparedStatement,变量处用 ? 代替。

在能使用 #{} 尽量使用它吧,可以防止sql注入。

以下是一个OGNL的调用静态方法的示例:

    <select id="getRecentQuestionTitle" parameterType="java.lang.String" resultType="java.lang.String">
            select title from song_question where questionState = #{value}
            <if test="@Ognl@isSolve(value[0],0)">
            order by questionTime desc
            </if>
            <if test="@Ognl@isSolve(value[0],1)">
            order by answerTime desc
            </if>
            limit 0,1
      </select>  

静态方法如下:

public static boolean isSolve(Object o,String soleState){
        if(o == null)
            return false;
        String str = null;
        if(o instanceof String[]){
            String[]objects = (String[])o;
            str = objects[0];
        }else if(o instanceof Character){
            Character c = (Character) o;
            str =  Character.toString(c);
        }
            if(StringUtils.equals(str, soleState))
                return true;
        return false;  

    } 

如果值为0,则order by questionTime desc 根据字段questionTime排序。

如果值为1,则order by answerTime desc根据字段answerTime排序。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Mybatis 动态SQL的几种实现方法

    案例sql脚本 DROP DATABASE IF EXISTS `javacode2018`; CREATE DATABASE `javacode2018`; USE `javacode2018`; DROP TABLE IF EXISTS t_user; CREATE TABLE t_user( id int AUTO_INCREMENT PRIMARY KEY COMMENT '用户id', name VARCHAR(32) NOT NULL DEFAULT '' COMMENT '用户名'

  • Mybatis利用OGNL表达式处理动态sql的方法教程

    本文介绍的是关于Mybatis中用OGNL表达式处理动态sql的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 常用的Mybatis动态sql标签有6种: 1. if 语句 (简单的条件判断) 2. choose (when,otherwize) ,相当于Java 语言中的 switch ,与 jstl 中的choose 很类似. 3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀) 4. where (主要是用来简化sql语句中where条件判断

  • 自己动手实现mybatis动态sql的方法

    发现要坚持写博客真的是一件很困难的事情,各种原因都会导致顾不上博客.本来打算写自己动手实现orm,看看时间,还是先实现一个动态sql,下次有时间再补上orm完整的实现吧. 用过mybatis的人,估计对动态sql都不陌生,如果没有用过,就当看看热闹吧.我第一次接触mysql是在大四的时候,当时就觉得动态sql这东西很牛,很灵活,一直想搞明白怎么实现的,尽管当时已经能够写ioc,mvc和简单的orm框架(仿mybaits但是没有动态sql部分),但是仍然找不到mybatis核心的动态sql到底在哪

  • MyBatis中动态sql的实现方法示例

    1. 动态sql 动态sql是mybatis中的一个核心,什么是动态sql? 动态sql即对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接.组装. MyBatis的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号.有些时候,SQL语句where条件中,需要一些安全判断,例如按某一条件查询时如果传入的参数是空,此时查询出的结果很可

  • Mybatis如何使用ognl表达式实现动态sql

    本文讲述在mybatis中如何使用ognl表达式实现动态组装sql语句 新建Users实体类: public class Users { private Integer uid; private String userName; private String tel; //添加上面私有字段的get.set方法 } 新建一个Dao接口类,mybatis配置文件在配置namespace属性时需要加入这个类的完整类名,找到这个类里的方法执行: public interface UserDao { /*

  • 在Mybatis @Select注解中实现拼写动态sql

    现在随着mybatis plus的应用,越来越多的弱化了SQL语句,对于单表操作可以说几乎不需要进行自己编写SQL语句了,但对于多表查询操作目前mybatis plus还没有很好的支持,还需要自己编写SQL语句,如: import java.util.List; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.anno

  • mybatis的mapper特殊字符转移及动态SQL条件查询小结

    目录 前言 条件查询 快速入门 if标签 where标签 choose when otherwise标签 foreach标签 场景案例 前言 我们知道在项目开发中之前使用数据库查询,都是基于jdbc,进行连接查询,然后是高级一点jdbcTemplate进行查询,但是我们发现还是不是很方便,有大量重复sql语句,与代码偶合,效率低下,于是就衍生出来ORM框架,如Mybatis,Hibernate,还有SpringBoot的,Spring Data JPA 条件查询 我们知道在mybatis map

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

    其实MyBatis具有的一个强大的特性之一通常是它的动态 SQL 能力. 如果你有使用 JDBC 或其他 相似框架的经验,你就明白要动态的串联 SQL 字符串在一起是十分纠结的,确保不能忘了空格或在列表的最后省略逗号.Mybatis中的动态 SQL 可以彻底处理这种痛苦.对于动态SQL,最通俗简单的方法就是我们自己在硬编码的时候赋予各种动态行为的判断,而在Mybatis中,用一种强大的动态 SQL 语 言来改进这种情形,这种语言可以被用在任意映射的 SQL 语句中.动态 SQL 元素和使用 JS

  • MyBatis连接池的深入和动态SQL详解

    目录 一,Mybatis 连接池与事务深入 1.1 Mybatis 的连接池技术 1.1.1 Mybatis 连接池的分类 1.1.2 Mybatis 中数据源的配置 1.2 Mybatis 的事务控制 1.2.1 JDBC 中事务的回顾 1.2.2 Mybatis 中事务提交方式 1.2.3 Mybatis 自动提交事务的设置 二.Mybatis 的动态 SQL 语句 2.1 动态 SQL 之标签 2.1.1 持久层 Dao 接口 2.1.2 持久层 Dao 映射配置 2.1.3 测试 2.2

  • Mybatis在注解上如何实现动态SQL

    目录 在注解上实现动态SQL 注解的动态语句支持以下 注解方式动态sql写法和注意事项 判断字符串为空串 用单引号 大于等于用 小于等于用 在注解上实现动态SQL 使用Mybatis注解实现sql语句,但是有些时候有些字段是空的,这时候这个空的字段就要从条件查询语句中删除,这个时候就需要用到动态Sql. 注解的动态语句支持以下 trim where set foreach if choose when otherwise bind @Select({"<script> "

  • Mybatis学习笔记之动态SQL揭秘

    前言 MyBatis 的强大特性之一便是它的动态 SQL.所以今天小编在这里为大家介绍一下Mybatis的一个强大功能-动态SQL 动态SQL是Mybatis的一个强大的特性,在使用JDBC操作数据时,如果查询条件特别多,将条件串联成SQL字符串是一件非常痛苦的事情,通常的解决方法使写很多的if-else条件语句去判断和拼接,并确保不能忘了空格或在字段的最后省略逗号.Mybatis使用一种强大的动态SQL语言来改善这种情况 动态SQL基于OGNL的表达式,可使我们能方便地在SQL语句中实现某些逻

随机推荐