MyBatis:4

转载:http://www.cnblogs.com/xrq730/p/5289638.html

什么是动态SQL

MyBatis的一个强大特性之一通常是它的动态SQL能力。如果你有使用JDBC或其他相似框架的经验,你就明白条件串联SQL字符串在一起是多么地痛苦,确保不能忘了空格或者在列表的最后的省略逗号,动态SQL可以彻底处理这种痛苦。

通常使用动态SQL不可能是独立的一部分,MyBatis当然使用一种强大的动态SQL语言来改进这种情形,这种语言可以被用在任意映射的SQL语句中。

动态SQL元素和使用JSTL或其它相似的基于XML的文本处理器相似,在MyBatis之前的版本中,有很多元素需要了解,MyBatis3大大地提升了它们,现在用不到原先一半的元素就能工作了,MyBatis采用功能强大的基于OGNL的表达式来消除其他元素。

OK,介绍就到这儿,下面来进入动态SQL的学习吧。

if

在动态SQL中所做的最通用的事情就是包含部分where子句的条件,比如:

<select id="selectInCondition" parameterType="student" resultType="student">
    select * from student where studentId > #{studentId}
    <if test="studentName != null">
        and studentName = #{studentName};
    </if>
</select>

具体实现不写了,那么如果我这么调用:

List<Student> list = StudentOperator.getInstance().selectInCondition(0, "Jack", 0, null);

查询的就是studentId>0且studentName="Jack"的所有学生信息,如果换一种调用方式:

List<Student> list = StudentOperator.getInstance().selectInCondition(0, null, 0, null);

那么查询的就是studentId>0的所有学生信息。

多个where子句也是一样的,比如:

<select id="selectInCondition" parameterType="student" resultType="student">
    <![CDATA[
        select * from student where studentId > #{studentId}
    ]]>
    <if test="studentName != null and studentName != ‘Jack‘ ">
        and studentName = #{studentName}
    </if>
    <if test="studentAge != 0">
        and studentAge = #{studentAge};
    </if>
</select>

注意一下,能用"<![CDATA[ ... ]]>"尽量还是用,不过只包动态SQL外的内容。

另外,test里面可以判断字符串、整型、浮点型,大胆地写判断条件吧。如果属性是复合类型,则可以使用A.B的方式去获取复合类型中的属性来进行比较。

choose、when、otherwise

有时候我们不想应用所有的应用条件,相反我们想选择很多情况下的一种。和Java中的switch...case...类似,MyBasit提供choose元素。

上面的例子是两种if判断都可能存在,接下来使用choose、when、other做一些修改:

<select id="selectInCondition" parameterType="student" resultType="student">
    <![CDATA[
        select * from student where studentId > #{studentId}
    ]]>
    <choose>
        <when test="studentName != null">
            and studentName = #{studentName};
        </when>
        <when test="studentAge != 0">
            and studentAge = #{studentAge};
        </when>
        <otherwise>
            or 1 = 1;
        </otherwise>
    </choose>
</select>

两个when只能满足一个,都不满足则走other。还是注意一下这里的"<![CDATA[ ... ]]>",不可以包围整个语句。

trim、where、set

第一个例子已经示例了if的用法,但是这种用法有个缺陷----动态SQL外必须有where子句。

什么意思,因为很多时候我们需要where后面的子句都动态生成,而不是事先有一个where,这样就有问题,比如说:

<select id="selectInCondition" parameterType="student" resultType="student">
    <![CDATA[
        select * from student where
    ]]>
    <if test="studentName != null and studentName != ‘Jack‘ ">
        and studentName = #{studentName}
    </if>
    <if test="studentAge != 0">
        and studentAge = #{studentAge};
    </if>
</select>

如果所有条件都不匹配,那么生成的SQL语句将是:

select * from student where

这将导致查询失败。即使只满足一个查询条件还是有问题,比如满足studentName那个吧,生成的SQL语句将是:

select * from student where and studentName = #{studentName};

这个查询也会失败。

解决办法也有,一个讨巧的办法是用where 1 = 1的方式,即:

<select id="selectInCondition" parameterType="student" resultType="student">
    <![CDATA[
        select * from student where 1 = 1
    ]]>
    <if test="studentName != null and studentName != ‘Jack‘ ">
        and studentName = #{studentName}
    </if>
    <if test="studentAge != 0">
        and studentAge = #{studentAge};
    </if>
</select>

因为"1 = 1"永远满足,所以相当于给where加了一层true而已,此时动态SQL生成什么where判断条件就是什么。

另外一个解决办法是利用MyBatis中的一个简单处理方式,这在90%情况下都会有用而且。而在不能使用的地方,可以以自定义方式处理。加上一个简单的改变,所有的事情都会顺利进行:

<select id="selectInCondition" parameterType="student" resultType="student">
    <![CDATA[
        select * from student
    ]]>
    <where>
        <if test="studentName != null and studentName != ‘Jack‘ ">
            and studentName = #{studentName}
        </if>
        <if test="studentAge != 0">
            and studentAge = #{studentAge};
        </if>
    </where>
</select>

where元素知道如果由被包含的标记返回任意内容,就仅仅插入where。而且,如果以"and"或"or"开头的内容,那么就会跳过where不插入。

如果where元素没有做出你想要的,那么可以使用trim元素来自定义。比如,和where元素相等的trim元素是:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
…
</trim>

即:

<select id="selectInCondition" parameterType="student" resultType="student">
    select * from student
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
        <if test="studentName != null and studentName != ‘Jack‘ ">
            and studentName = #{studentName}
        </if>
        <if test="studentAge != 0">
            and studentAge = #{studentAge};
        </if>
    </trim>
</select>

特别要注意,prefixOverrides中的空白也是很重要的

最后一个小内容,和动态更新语句相似的解决方案是set。set元素可以被用于动态包含更新的列,而不包含不需要更新的。比如:

<update id="updateStudentAgeById" parameterType="Student">
    <!--update student set studentAge = #{studentAge} where
        studentId = #{studentId}; -->
    <![CDATA[
        update student
    ]]>
    <set>
        <if test="studentAge != 0">studentAge = #{studentAge}</if>
    </set>
    where studentId = #{studentId}
</update>

可以对比一下,注释掉的是原update语句,没有注释的是加入动态SQL之后的语句。

这里,set元素会动态前置set关键字,而且也会消除任意无关的逗号。如果你对和这里对等的trim元素好奇,它看起来是这样的:

<trim prefix="SET" prefixOverrides=",">
…
</trim>

这种时候我们附加一个后缀,同时也附加一个前缀。

foreach

另外一个动态SQL通用的必要操作时迭代一个集合,通常是构建在in条件中的。比如(上面的例子都是我在自己电脑上跑通过的例子,这个例子就直接复制MyBatis官方文档上的内容了):

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

foreach是非常强大的,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内。他也允许你指定开放和关闭字符串,在迭代之间放置分隔符。这个元素是很智能的,它不会偶然地附加多余的分隔符。

时间: 2024-12-17 09:54:02

MyBatis:4的相关文章

使用MyBatis Generator自动生成实体、mapper和dao层

通过MyBatis Generator可以自动生成实体.mapper和dao层,记录一下怎么用的. 主要步骤: 关于mybatis从数据库反向生成实体.DAO.mapper: 参考文章:http://www.cnblogs.com/wangkeai/p/6934683.html第一种方式:main方法运行(推荐) 1.在pom.xml中加入插件依赖: 2.写mbgConfiguration.xml文件,jdbc.properties文件 3.写/SSM/src/main/java/main/Ge

SSM整合(spring,spirngmvc,mybatis)

整合思路   准备环境:导入jar包(spring mybatis  dbcp连接池  mysql驱动包 log4j) 工程结构: --------------------------- 1.  整合dao mybatis和spring进行整合   applicationContext-dao.xml 配置: 1.数据源 2.SqlSessionFactory 3.mapper扫描器 创建po以及mapper(通过逆向工程,这里不再演示) 针对综合查询mapper,一般情况会有关联查询,建议自定

SpringBoot 2.SpringBoot整合Mybatis

一.创建Springboot的配置文件:application.properties SpringApplication 会从 application.properties 文件中加载配置信息,下面是添加Spring配置信息的文件目录顺序: 当前目录下的/config子目录中 当前目录中 一个 classpath 包下的 /config 目录中 classpath 根目录中 大家根据自己习惯来即可. /application.properties 文件配置如下: spring.datasourc

springMVC+MyBatis+Spring 整合(3)

spring mvc 与mybatis 的整合. 加入配置文件: spring-mybaits.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xm

MyBatis学习(四)XML配置文件之SQL映射的XML文件

SQL映射文件常用的元素: 1.select 查询语句是MyBatis最常用的语句之一. 执行简单查询的select元素是非常简单的: <select id="selectUser" parameterType="int" resultType="hashmap"> SELECT * FROM PERSON WHERE ID = #{id} </select> 这个语句被称作selectUser,接受一个int类型的参数,

MyBatis框架中Mapper映射配置的使用及原理解析(七) MapperProxy,MapperProxyFactory

从上文<MyBatis框架中Mapper映射配置的使用及原理解析(六) MapperRegistry> 中我们知道DefaultSqlSession的getMapper方法,最后是通过MapperRegistry对象获得Mapper实例: public <T> T getMapper(Class<T> type, SqlSession sqlSession) { final MapperProxyFactory<T> mapperProxyFactory =

2017年9月3日 Spring及Mybatis中连接数据库的不同方式

连接数据库用spring和mybatis中使用的方法可以不同,mybaits可以不用写数据库的配置文件 Spring的连接方法 <!-- 读取属性文件(.properties)的内容 --> <!-- location:指定要读取的属性文件的位置及文件名. 注: classpath:表示依据类路径去查找 容器依据路径读取属性文件的内容, 并且将这些内容存放到Properties对象上 --> //数据库的登入数据文件 //文件名db.properties #db connectio

mybatis中&quot;#&quot;和&quot;$&quot;的区别

mybatis中"#"和"$"的区别 动态 sql 是 mybatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析.mybatis 为我们提供了两种支持动态 sql 的语法:#{} 以及 ${}. 在下面的语句中,如果 username 的值为 zhangsan,则两种方式无任何区别: select * from user where name = #{name}; select * from

mybatis中的mapper接口文件以及example类的实例函数以及详解

##Example example = new ##Example(); example.setOrderByClause("字段名 ASC"); //升序排列,desc为降序排列. example.setDistinct(false)//去除重复,boolean型,true为选择不重复的记录. Criteria criteria = new Example().createCriteria(); is null;is not null; equal to(value);not equ

mybatis与hibernate的区别

本文转载自:http://blog.csdn.net/wangpeng047/article/details/17038659 以前没怎么用过mybatis,只知道与hibernate一样是个orm数据库框架.随着使用熟练度的增加,发现它与hibernate区别是非常大的,结合至今为止的经验,总结出以下几点: 1. hibernate是全自动,而mybatis是半自动. hibernate完全可以通过对象关系模型实现对数据库的操作,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql