MyBatis 的强大特性之一便是它的动态 SQL。可以根据不同条件拼接 SQL 语句。

动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。主要由以下几种元素。

  • if
  • where
  • trim
  • choose (when, otherwise)
  • set
  • foreach
  • bind

1、if  (判断)

实例:根据条件查询酒店列表

hotelMapper接口

package com.pjf.mybatis.dao;

import java.util.List;
import com.pjf.mybatis.po.Hotel; public interface HotelMapper { public List<Hotel> getHotel(Hotel hotel); }

hotelMapper.xml

<?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="com.pjf.mybatis.dao.HotelMapper"> <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
<result column="hotel_address" property="hotelAddress"
jdbcType="VARCHAR" />
<result column="price" property="price" jdbcType="INTEGER" />
</resultMap> <!-- resultMap使用 -->
<select id="getHotel" resultMap="myHotel">
select*
from hotel
where
<if test="id!=null">
id=#{id}
</if>
<if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
and hotel_name like concat('%',#{hotelName},'%')
</if>
<if test="price!=null">
and price> #{price}
</if>
</select>
</mapper>

测试类

package com.pjf.mybatis;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test; import com.pjf.mybatis.dao.HotelMapper;import com.pjf.mybatis.po.Hotel; public class TestHotel { public SqlSessionFactory sqlSessionFactory() throws IOException {
// mybatis的配置文件
String resource = "mybatis_config.xml";
// 使用类加载器加载mybatis的配置文件(它也加载关联的映射文件)TestHotel.class.getClassLoader()
InputStream is = Resources.getResourceAsStream(resource);
// 构建sqlSession的工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
return sessionFactory;
} @Test
public void getHotel() throws IOException { SqlSessionFactory sessionFactory = sqlSessionFactory();
SqlSession session = sessionFactory.openSession();
HotelMapper hotelMapper = session.getMapper(HotelMapper.class);
System.out.println(hotelMapper.getClass());
Hotel hotel = new Hotel(1001, "南京", "", 800);
List<Hotel> list = hotelMapper.getHotel(hotel);
for (Hotel hotel1 : list) {
System.out.println(hotel1);
}
session.close();
}
}

查看结果

需要注意的是特殊字符需要转义,

<if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">

常用的有以下字符

2、where

对于上面的查询条件,如果在测试类中

Hotel hotel = new Hotel(1001, "南京", "", 800);改成 Hotel hotel = new Hotel(null,"南京","", 800);
结果会怎么样

sql多了一个and

解决:

a、增加默认条件1=1

<?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="com.pjf.mybatis.dao.HotelMapper"> <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
<result column="hotel_address" property="hotelAddress"
jdbcType="VARCHAR" />
<result column="price" property="price" jdbcType="INTEGER" />
</resultMap> <!-- resultMap使用 -->
<select id="getHotel" resultMap="myHotel">
select*
from hotel
where 1=1
<if test="id!=null">
id=#{id}
</if>
<if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
and hotel_name like concat('%',#{hotelName},'%')
</if>
<if test="price!=null">
and price> #{price}
</if>
</select>
</mapper>

结果

b、增加where元素

将所有的元素放在where标签内,where元素会自动去除首位的and或or。注意是首位的and或者or。

<?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="com.pjf.mybatis.dao.HotelMapper"> <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
<result column="hotel_address" property="hotelAddress"
jdbcType="VARCHAR" />
<result column="price" property="price" jdbcType="INTEGER" />
</resultMap> <!-- resultMap使用 -->
<select id="getHotel" resultMap="myHotel">
select*
from hotel
<where>
<if test="id!=null">
id=#{id}
</if>
<if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
and hotel_name like concat('%',#{hotelName},'%')
</if>
<if test="price!=null">
and price> #{price}
</if>
</where>
</select>
</mapper>

3、trim  (字符串截取)

如果and写在语句的末尾,该怎么解决呢

<?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="com.pjf.mybatis.dao.HotelMapper"> <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
<result column="hotel_address" property="hotelAddress"
jdbcType="VARCHAR" />
<result column="price" property="price" jdbcType="INTEGER" />
</resultMap> <!-- resultMap使用 -->
<select id="getHotel" resultMap="myHotel">
select*
from hotel
<where>
<if test="id!=null">
id=#{id} and
</if>
<if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
hotel_name like concat('%',#{hotelName},'%') and
</if>
<if test="price!=null">
price> #{price}
</if>
</where>
</select>
</mapper>

测试类

package com.pjf.mybatis;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test; import com.pjf.mybatis.dao.HotelMapper;
import com.pjf.mybatis.po.City;
import com.pjf.mybatis.po.Hotel; public class TestHotel { public SqlSessionFactory sqlSessionFactory() throws IOException {
// mybatis的配置文件
String resource = "mybatis_config.xml";
// 使用类加载器加载mybatis的配置文件(它也加载关联的映射文件)TestHotel.class.getClassLoader()
InputStream is = Resources.getResourceAsStream(resource);
// 构建sqlSession的工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
return sessionFactory;
} @Test
public void getHotel() throws IOException { SqlSessionFactory sessionFactory = sqlSessionFactory();
SqlSession session = sessionFactory.openSession();
HotelMapper hotelMapper = session.getMapper(HotelMapper.class);
Hotel hotel = new Hotel(1001,"南京","",null);
System.out.println(hotel);
List<Hotel> list = hotelMapper.getHotel(hotel);
for (Hotel hotel1 : list) {
System.out.println(hotel1);
}
session.close();
}
}

结果:末尾就会多一个and

这时候就可以通过trim标签来解决:

trim 对trim标签体中拼接后的字符串进行操作

   prefix       对拼接后的字符串加前缀
prefixOverrides 对拼接后的字符串去前缀
suffix 对拼接后的字符串加后缀
suffixOverrides 对拼接后的字符串去后缀
<?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="com.pjf.mybatis.dao.HotelMapper"> <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
<result column="hotel_address" property="hotelAddress"
jdbcType="VARCHAR" />
<result column="price" property="price" jdbcType="INTEGER" />
</resultMap> <select id="getHotel" resultMap="myHotel">
select*
from hotel
<!-- trim 对trim标签体中拼接后的字符串进行操作
prefix 对拼接后的字符串加前缀
prefixOverrides 对拼接后的字符串去前缀
suffix 对拼接后的字符串加后缀
suffixOverrides 对拼接后的字符串去后缀
-->
<trim prefix="where" prefixOverrides="" suffix="" suffixOverrides="and">
<if test="id!=null">
id=#{id} and
</if>
<if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
hotel_name like concat('%',#{hotelName},'%') and
</if>
<if test="price!=null">
price> #{price}
</if>
</trim>
</select>
</mapper>

这样就解决了

4、choose (分支选择)

MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。,但不同的是mybatis进入了一个分支后就不再进入其他分支。

<?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="com.pjf.mybatis.dao.HotelMapper"> <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
<result column="hotel_address" property="hotelAddress"
jdbcType="VARCHAR" />
<result column="price" property="price" jdbcType="INTEGER" />
</resultMap>
<select id="getHotel" resultMap="myHotel">
select*
from hotel
<where>
<choose>
<when test="id!=null">
id=#{id}
</when>
<when test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
hotel_name like concat('%',#{hotelName},'%')
</when>
<when test="hotelAddress!=null &amp;&amp; hotelAddress!=&quot;&quot;">
hotel_address=#{hotelAddress}
</when>
<when test="price!=null">
price>#{price}
</when>
<otherwise>
1=1
</otherwise>
</choose>
</where>
</select>
</mapper>

5、set

前面我们使用update可以进行全字段更新,但是如果是带了什么字段就更新什么字段,该怎么做呢。

可是使用set和if的结合,此外,set标签能自动删除末尾多余的逗号。

<?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="com.pjf.mybatis.dao.HotelMapper"> <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
<result column="hotel_address" property="hotelAddress"
jdbcType="VARCHAR" />
<result column="price" property="price" jdbcType="INTEGER" />
</resultMap> <update id="updateHotel">
update hotel
<set>
<if test="hotelName!=null">
hotel_name=#{hotelName},
</if>
<if test="price!=null">
price=#{price}
</if>
</set>
<where>
id=#{id}
</where>
</update>
</mapper>

6、foreach

用来对集合进行遍历

<?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="com.pjf.mybatis.dao.HotelMapper"> <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
<result column="hotel_address" property="hotelAddress"
jdbcType="VARCHAR" />
<result column="price" property="price" jdbcType="INTEGER" />
</resultMap> <!-- resultMap使用 -->
<select id="getHotel" resultMap="myHotel">
select*
from hotel where id in
<!-- collection 指要遍历的集合 1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key
item 将遍历出的元素赋值给指定的变量
separator 每个元素之间的分隔符
open 遍历出的结果拼接出一个开始符
close 遍历出的结果拼接一个结束符
index 索引
-->
<foreach collection="list" item="ids" separator="," open="(" close=")">
#{ids}
</foreach>
</select>
</mapper>

测试类

package com.pjf.mybatis;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test; import com.pjf.mybatis.dao.HotelMapper;
import com.pjf.mybatis.po.City;
import com.pjf.mybatis.po.Hotel; public class TestHotel { public SqlSessionFactory sqlSessionFactory() throws IOException {
// mybatis的配置文件
String resource = "mybatis_config.xml";
// 使用类加载器加载mybatis的配置文件(它也加载关联的映射文件)TestHotel.class.getClassLoader()
InputStream is = Resources.getResourceAsStream(resource);
// 构建sqlSession的工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
return sessionFactory;
} @Test
public void getHotel() throws IOException { SqlSessionFactory sessionFactory = sqlSessionFactory();
SqlSession session = sessionFactory.openSession(true);
HotelMapper hotelMapper = session.getMapper(HotelMapper.class);
List<Integer> id =new ArrayList<Integer>();
id.add(1001);
id.add(1002);
id.add(1003);
List<Hotel> list= hotelMapper.getHotel(id);
for (Hotel hotel : list) {
System.out.println(hotel);
}
session.close();
}
}

7、bind

bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。

<select id="getHotel" resultMap="myHotel">
<bind name="_hotelName" value="'%' + hotelName + '%'" />
SELECT * FROM hotel
WHERE hotel_name LIKE #{_hotelName}
</select>

mybatis学习(九)——动态sql的更多相关文章

  1. mybatis学习 十 动态 SQL

    1.  根据方法传入的参数不同执行不同的 SQL 命令.称为动态 SQL, MyBatis 中动态 SQL 就是在 mapper.xml 中添加逻辑判断等. 2. <if>标签 <s ...

  2. mybatis学习之动态sql

    mybatis的动态sql语句很强大,在mapper映射文件中使用简单的标签即可实现该效果,下面一个个记录: 1.select查询 简单的select类似如下: <select id=" ...

  3. mybatis 学习五 动态SQL语句

    3.1 selectKey 标签 在insert语句中,在Oracle经常使用序列.在MySQL中使用函数来自动生成插入表的主键,而且需要方法能返回这个生成主键.使用myBatis的selectKey ...

  4. Mybatis学习笔记-动态SQL

    概念 根据不同环境生成不同SQL语句,摆脱SQL语句拼接的烦恼[doge] 本质:SQL语句的拼接 环境搭建 搭建数据库 CREATE TABLE `blog`( `id` VARCHAR(50) N ...

  5. 【mybatis深度历险系列】mybatis中的动态sql

    最近一直做项目,博文很长时间没有更新了,今天抽空,学习了一下mybatis,并且总结一下.在前面的博文中,小编主要简单的介绍了mybatis中的输入和输出映射,并且通过demo简单的介绍了输入映射和输 ...

  6. Mybatis入门之动态sql

    Mybatis入门之动态sql 通过mybatis提供的各种标签方法实现动态拼接sql. 1.if.where.sql.include标签(条件.sql片段) <sql id="sel ...

  7. mybatis 详解------动态SQL

    mybatis 详解------动态SQL   目录 1.动态SQL:if 语句 2.动态SQL:if+where 语句 3.动态SQL:if+set 语句 4.动态SQL:choose(when,o ...

  8. mybatis中的动态SQL

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

  9. Mybatis映射文件动态SQL语句-01

    因为在很多业务逻辑复杂的项目中,往往不是简单的sql语句就能查询出来自己想要的数据,所有mybatis引入了动态sql语句, UserMapper.xml <?xml version=" ...

  10. Java数据持久层框架 MyBatis之API学习九(SQL语句构建器详解)

    对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...

随机推荐

  1. CornerStone使用跳坑总结

    Cornerstone是专门为Mac用户设计的Subversion(SVN)的控制,使版本控制更加透明.cornerstone根Xcode相比,能够更好的忽略文件,所以除了项目经理第一次初始化项目的时 ...

  2. Dede技巧

    解决DEDE图集上传图片时跳出302错误   本地上传图集的时候突然提示网页出错,还爆出302错误. 解决办法是在include/userlogin.class.php文件中的第二行session_s ...

  3. Yii2应用的运行过程

    每一个框架都有一个入口脚本,Yii2也不例外.一般来说,对于Web应用的入口脚本是YiiBasePath/frontend/web目录下的index.php. 先观察这个文件: <?php de ...

  4. linux关于任务计划

    1.一次性任务计划:at 1)添加 在18:16时候重启服务器 at 18:16 >at init 6 >at ctrl+d2)查看 atq 1 Mon Aug 20 21:09:00 2 ...

  5. python入门:输出1-100之内的所有奇数和偶数(自写)

    #!/urs/bin/env python # -*- coding:utf-8 -*- #输出1-100之内的所有奇数和偶数(自写) """ 给x赋值等于1,wehil ...

  6. 给vagrant中的precise64升级VBoxGuestAdditions

    位置:/usr/share/virtualbox/VBoxGuestAdditions.iso 在host(ubuntu 12.04 64)中: 查看虚拟机的名字:jb@H38:~/vm/vagran ...

  7. HTTP认证之摘要认证——Digest(二)

    导航 HTTP认证之基本认证--Basic(一) HTTP认证之基本认证--Basic(二) HTTP认证之摘要认证--Digest(一) HTTP认证之摘要认证--Digest(二) 在HTTP认证 ...

  8. Linux学习-延伸正则表达式

    grep 默认仅支持基础正则表达式,如果要使用延伸型正则 表达式,你可以使用 grep -E , 不过更建议直接使用 egrep !直接区分指令比较好记忆!其 实 egrep 与 grep -E 是类 ...

  9. luogu1972 [SDOI2009]HH的项链

    莫队裸题还不带修改 #include <algorithm> #include <iostream> #include <cstdio> #include < ...

  10. 十分钟了解HTTP协议

    概念 HTTP(Hypertext Transfer Protocol,超文本传输协议)是TCP/IP协议的应用(封装). HTTP协议是单向通讯,无状态,主要应用于B/S模型的网络软件,客户端一(多 ...