最近一直做项目,博文很长时间没有更新了,今天抽空,学习了一下mybatis,并且总结一下。在前面的博文中,小编主要简单的介绍了mybatis中的输入和输出映射,并且通过demo简单的介绍了输入映射和输出映射,今天这篇博文,小编主要来简单的介绍一下mybatis中的动态sql,有的小伙伴会问,既然有动态sql,那是不是也应该存在静态sql,答案是肯定的。那么什么是静态sql呢,静态sql语句一般用于嵌入式sql应用中,在程序运行之前,sql语句必须是确定的,例如sql语句中涉及的列名和表名必须是存在的,静态sql语句的编译是在应用程序运行前进行的,编译的结果会存储在数据库内容,而后程序进行时,数据库将直接执行编译好的sql语句,降低运行时的开销。所谓的动态sql,是在应用程序运行时被编译和执行的,例如使用DB2的交互式工具CLP访问数据库时,用户输入的sql语句是不确定的,因此sql语句只能被动态的编译,动态的sql的应用较多,常见的CLI和JDBC应用程序都使用动态sql。这篇博文小编主要分三个部分来分别进行介绍,动态sql、sql片段和foreach。

一、动态sql

1.1定义

mybatis核心对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接,组装。

1.2案例需求

用户信息综合查询列表这个statment的定义使用动态sql,对查询条件进行判断,如果输入参数不为空进行查询拼接。

1.3UserMapper.xml

<!-- 用户信息综合查询
    #{userCustom.sex}:取出pojo包装对象中性别值
    ${userCustom.username}:取出pojo对象中用户名称
-->
    <select id="findUserList" parameterType="com.mybatis.entity.UserQueryVo"
    resultType="com.mybatis.entity.UserCustom">
        select * from t_user
        <!-- 动态sql查询:where可以自动去掉第一个and -->
        <where>
            <if test="userCustom!=null">
                <if test="userCustom.sex!=null and userCustom.sex!='' ">
                    and sex=#{userCustom.sex}
                </if>
                <if test="userCustom.username!=null and userCustom.username!='' ">
                    and username=#{userCustom.username}
                </if>
            </if>
        </where>
<!--          where sex=#{userCustom.sex} and username LIKE '%${userCustom.username}%' -->
    </select>

1.4测试代码

@Test
    public void testFindUserList() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //创造查询条件
        UserQueryVo userQueryVo = new UserQueryVo();
        UserCustom userCustom = new UserCustom();
//        userCustom.setSex("2");
        //这里使用动态sql,如果不设置某个值,条件不会拼接sql中
        userCustom.setUsername("小");
        userQueryVo.setUserCustom(userCustom);
        // 创建Usermapper对象,mybatis自动生成mapper代理对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<UserCustom>list=mapper.findUserList(userQueryVo);
        //测试动态sql,属性的非空判断测试
//        List<UserCustom>list=mapper.findUserList(null);
        System.out.println(list);
        sqlSession.commit();
        sqlSession.close();
    }

二、sql片段

2.1需求

将上边的动态sql判断代码抽取出来,组成一个sql片段,其她的statment中就可以引用sql片段,方便开发。

2.2定义sql片段

<!-- 定义sql片段,Id是唯一标识
         建议:是基于单表来定义sql片段,这样的话sql片段的可重用性才高,在sql片段中不要包含where
     -->
    <sql id="query_user_where" >
        <if test="userCustom!=null">
                <if test="userCustom.sex!=null and userCustom.sex!='' ">
                    and sex=#{userCustom.sex}
                </if>
               <if test="userCustom.username!=null and userCustom.username!='' ">
                    and username=#{userCustom.username}
                </if>
            </if>
    </sql>

2.3在mapper.xml中定义的statment中引用sql片段

<!-- 用户信息综合查询
    #{userCustom.sex}:取出pojo包装对象中性别值
    ${userCustom.username}:取出pojo对象中用户名称
-->
    <select id="findUserList" parameterType="com.mybatis.entity.UserQueryVo"
    resultType="com.mybatis.entity.UserCustom">
        select * from t_user
        <!-- 动态sql查询:where可以自动去掉第一个and -->
        <where>
        <!-- 引用sql片段的id,如果refid指定的不在本mapper.xml中,需要前边加namespace -->
            <include refid="query_user_where"></include>
            <!-- 这里可以引用其它的sql片段 -->
        </where>
    </select>

三、foreach

作用:向sql传递数据或者list,mybatis使用foreach解析,在用户查询列表和查询总数的statment中增加多个id输入查询。

3.1需求:sql语句如下,两种方法:

SELECT * FROM t_user WHERE id=1 OR id=10 OR id=16

SELECT * FROM t_user WHERE id IN(1,10,16)

3.2在输入参数包装类型中添加List<Integer>ids传入多个id

package com.mybatis.entity;

import java.util.List;

/**
 *
 * @ClassName: UserQueryVo
 * @Description: TODO(包装类型)
 * @author 丁国华
 *
 */
public class UserQueryVo {

    public List<Integer> ids;

    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }
}

3.3mapper.xml代码

<!-- 实现下边的sql拼接
            select * from t_user where id=1 OR id=2 OR id=3
    -->
    <select id="findUserByIds" parameterType="com.mybatis.entity.UserQueryVo"
    resultType="com.mybatis.entity.User">
            select * from t_user
        <where>
                <if test="ids!=null">
                <!-- 使用foreach遍历ids
                    collection:指定输入对象的集合属性
                    item:每个遍历生成对象中
                    open:开始遍历时拼接的串
                    close:技术遍历时拼接的串
                    separator:遍历的两个对象中需要拼接的串
                 -->
                <foreach collection="ids" item="user_id" open="AND (" close=")" separator="or">
                    id=#{user_id}
                </foreach>
            </if>
        </where>
    </select>

select *from t_user where id in(1,2,3)的mapper.xml配置

<select id="findUserByIds" parameterType="com.mybatis.entity.UserQueryVo"
    resultType="com.mybatis.entity.User">
            select * from t_user
        <where>
                <if test="ids!=null">
                <!--
                    使用foreach遍历ids
                    collection:指定输入对象的集合属性
                    item:每个遍历生成对象中
                    open:开始遍历时拼接的串
                    close:技术遍历时拼接的串
                    separator:遍历的两个对象中需要拼接的串
                 -->
                <!-- 实现“ select * from t_user where  id in(1,2,3)”拼接 -->
                <foreach collection="ids" item="user_id" open="AND id in ("  close=")" separator=",">
                    id=#{user_id}
                </foreach>
            </if>
        </where>
    </select>
userMapper.java代码
 public interface UserMapper {
    //ids查询用户数据
     public List<User> findUserByIds(UserQueryVo userQueryVo);
 }

Junit测试代码

@Test
    public void findUserByIdsTest() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 创建Usermapper对象,mybatis自动生成mapper代理对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //创造查询条件
        UserQueryVo userQueryVo = new UserQueryVo();
        //传入多个id
        List<Integer> ids=new ArrayList<Integer>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        //将ids通过userQueryVo传入statement中
        userQueryVo.setIds(ids);
        //调用userMapper的代码
        List<UserCustom> userList= mapper.findUserList(userQueryVo);
        System.out.println(userList);
        sqlSession.close();
    }

小编寄语:该博文小编主要简单的介绍了mybatis中的动态sql,MyBatis的一个强大的特性之一通常是它的动态 SQL 能力。如果你有使用 JDBC 或其他相似框架的经验,你就明白条件地串联 SQL字符串在一起是多么的痛苦,确保不能忘了空 格或在列表的最后省略逗号。动态 SQL可以彻底处理这种痛苦。通常使用动态SQL不可能是独立的一部分,MyBatis当然使用一种强大的动态SQL语言来改进这种情形,这种语言可以被用在任意映射的SQL语句中。

动态SQL元素和使用JSTL或其他相似的基于XML的文本处理器相似。在MyBatis之前的版本中,有很多的元素需要来了解。MyBatis3大大提升了它们,现在用不到原先一半的元素就能工作了。MyBatis采用功能强大的基于OGNL的表达式来消除其他元素。 小编博文,小编将继续介绍mybatis的相关知识,敬请期待`(*∩_∩*)′。

【mybatis深度历险系列】mybatis中的动态sql的更多相关文章

  1. 【mybatis深度历险系列】mybatis中的输入映射和输出映射

    在前面的博文中,小编介绍了mybatis的框架原理以及入门程序,还有mybatis中开发到的两种方法,原始开发dao的方法和mapper代理方法,今天博文,我们来继续学习mybatis中的相关知识,随 ...

  2. 【mybatis深度历险系列】mybatis的框架原理+入门程序解析

    在前面的博文中,小编介绍了springmvc的相关知识点,在今天这篇博文中,小编将介绍一下mybatis的框架原理,以及mybatis的入门程序,实现用户的增删改查,她有什么优缺点以及mybatis和 ...

  3. 【mybatis深度历险系列】延迟加载

    在前面的博文中,小编主要简单的介绍了mybatis中的高级映射,小伙伴们可以把mybatis和hibernate的因素进行对比,更加有利于理解.今天这篇博文,小编主要来简单介绍一下mybatis中的延 ...

  4. 【mybatis深度历险系列】深入浅出mybatis中原始dao的开发和mapper代理开发

    使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法.mybatis在进行dao开发的时候,涉及到三姐妹,分别是SqlSessionFactoryBuilder ...

  5. 【mybatis深度历险系列】mybatis中的高级映射一对一、一对多、多对多

    学习hibernate的时候,小编已经接触多各种映射,mybatis中映射有到底是如何运转的,今天这篇博文,小编主要来简单的介绍一下mybatis中的高级映射,包括一对一.一对多.多对多,希望多有需要 ...

  6. Mybatis 系列9-强大的动态sql 语句

    [Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...

  7. mybatis中的动态SQL

    在实际开发中,数据库的查询很难一蹴而就,我们往往要根据各种不同的场景拼接出不同的SQL语句,这无疑是一项复杂的工作,我们在使用mybatis时,mybatis给我们提供了动态SQL,可以让我们根据具体 ...

  8. MyBatis基础入门《二十》动态SQL(foreach)

    MyBatis基础入门<二十>动态SQL(foreach) 1. 迭代一个集合,通常用于in条件 2. 属性 > item > index > collection : ...

  9. MyBatis基础入门《十九》动态SQL(set,trim)

    MyBatis基础入门<十九>动态SQL(set,trim) 描述: 1. 问题 : 更新用户表数据时,若某个参数为null时,会导致更新错误 2. 分析: 正确结果: 若某个参数为nul ...

随机推荐

  1. NPM实用指北

    npm作为下载node附送的大礼包,大家一定不会陌生. 然而关于npm,估计大量的只是用到npm install XXX以及npm run XXX. 其实这里边还有很多有意思的命令&参数.关于 ...

  2. delete和delete[]的区别(转载)

    一直对C++中的delete和delete[]的区别不甚了解,今天遇到了,上网查了一下,得出了结论.做个备份,以免丢失. C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete ...

  3. ●洛谷P3687 [ZJOI2017]仙人掌

    题链: https://www.luogu.org/problemnew/show/P3687题解: 计数DP,树形DP. (首先对于这个图来说,如果初始就不是仙人掌,那么就直接输出0) 然后由于本来 ...

  4. hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi'an Online)

    Mart Master II Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  5. 2015 多校联赛 ——HDU5402(模拟)

    For each test case, in the first line, you should print the maximum sum. In the next line you should ...

  6. python中type dtype astype 的用法

    1.type 获取数据类型 2.dtype 数组元素的类型 3.astype 修改数据类型

  7. c++中双冒号的作用

    双冒号(::)用法 参考链接:https://segmentfault.com/a/1190000000345680 1.表示“域操作符”例:声明了一个类A,类A里声明了一个成员函数void f(), ...

  8. 解决ansible首次连接host服务器需验证问题

    问题描述: [root@iZm5e79rtwsq2hm57teyk5Z ansible]# ansible aofeng -f 5 -m ping 47.93.18.191 | FAILED! =&g ...

  9. DS4700电池更换步骤

    DS4700电池更换步骤: 在A控制器里操作(带电热插拔控制器)对逻辑盘进行切换: (需要先将A控下挂的硬盘手工切换到B控上.然后对A控进行电池更换,更换完成后再将原A控下挂硬盘切回) 如下详细步骤: ...

  10. 【SpringMVC】<context:include-filter>和<context:exclude-filter>使用时要注意的地方

    http://jinnianshilongnian.iteye.com/blog/1762632 http://blog.51cto.com/wenshengzhu/1700340 http://ww ...