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. 批量格式化json

    单个文件格式化工具: vscode和sublime都有格式化json的插件. 但是笔者遇到的情况是有几百个文件需要格式化,不可能每个文件都打开,进行分别格式化. 于是写了一个python脚本,非常强大 ...

  2. HTML_3

    html列表 有序列表:在网页上定义一个有编号的内容列表可以用<ol>.<li>配合使用来实现,在网页上生成的列表,每条项目上按1.2.3编号,有序列表在实际开发中较少使用.代 ...

  3. Mysql command line

    show databasename; use databasename; show tables; desc tablename;

  4. PayPal为什么从Java迁移到Node.js 性能提高一倍 文件代码减少44%

    大家都知道PayPal是另一家迁移到Node.js平台的大型公司,Jeff Harrell的这篇博文 Node.js at PayPal  解释了为什么从Java迁移出来的原因: 开发效率提高一倍(2 ...

  5. lua拷贝二进制文件的方法

    使用lua拷贝二进制文件相比文本文件复杂一点,方法如下 function copyFunc(targetPath,sourcePath) local rf = io.open(sourcePath,& ...

  6. Tarjan算法 详解+心得

    Tarjan算法是由Robert Tarjan(罗伯特·塔扬,不知有几位大神读对过这个名字) 发明的求有向图中强连通分量的算法. 预备知识:有向图,强连通. 有向图:由有向边的构成的图.需要注意的是这 ...

  7. Python基础——时间

    导入时间模块 import time 时间戳 print(time.time()) 获取本地时间 print(time.localtime(time.time())) 时间显示格式化 print(ti ...

  8. Survey lists 10 most innovative cities

    From China Daily Beijing and Shanghai are among the 10 most innovative cities in the world, based on ...

  9. Android兼容性测试CTS --环境搭建、测试执行、结果分析

    为了确保Android应用能够在所有兼容Android的设备上正确运行,并且保持相似的用户体验,在每个版本发布之时,Android提供了一套兼容性测试用例集合(Compatibility Test S ...

  10. HBase0.94.2-cdh4.2.0需求评估测试报告1.0之一

    hbase是bigtable的开源山寨版本.是建立的hdfs之上,提供高可靠性.高性能.列存储.可伸缩.实时读写的数据库系统.它介于nosql和RDBMS之间,仅能通过主键(row key)和主键的r ...