MyBatis 的强大特性之一便是它的动态 SQL,本章介绍动态 SQL

  查看本章,请先阅读【Mybatis】MyBatis对表执行CRUD操作(三)

  本例表结构

 CREATE TABLE `employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`last_name` varchar(255) DEFAULT NULL,
`gender` char(1) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

if

  if标签:用于逻辑判断,其中test属性,填写的是判断表达式(OGNL)

  示例

  1、EmployeeMapper新增Sql如下:

 <!-- if:判断 -->
<select id="testConditionIf"
resultType="com.hd.test.pojo.Employee">
select id, last_name lastName, gender from employee
<!--
test:判断表达式(OGNL) OGNL参照PPT或者官方文档。
c:if test 从参数中取值进行判断 遇见特殊符号应该去写转义字符: &&: -->
where 1 = 1
<if test="id != null">
AND id = #{id}
</if>
<!-- 表达式中,字符串使用''单引号引起来 -->
<if test="lastName != null and lastName.trim() != ''">
AND last_name = #{lastName}
</if>
<!-- ognl会进行字符串与数字的转换判断 "0"==0 -->
<if test="gender==0 or gender==1">
AND gender = #{gender}
</if>
<!-- 转义字符: &amp;&amp; == && &quot;&quot; == ""-->
<if test="email != null &amp;&amp; lastName!=&quot;&quot;">
AND email = #{email}
</if>
</select>

  2、EmployeeMapper接口中,新增方法

 public List<Employee> testConditionIf(Employee employee);

  3、测试方法

 @Test
public void test001() throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sessionFactory.openSession(); try {
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> list = mapper.testConditionIf(new Employee(null, "0", null));
System.out.println(list.size());
for (Employee employee : list) {
System.out.println(list);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}

  4、执行结果

    

choose

  有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

  示例

  1、EmployeeMapper新增Sql如下:

 <!-- choose -->
<select id="testConditionChoose" resultType="com.hd.test.pojo.Employee">
select id, last_name lastName, gender from employee
where 1 = 1
<choose>
<when test="id != null">
AND id = #{id}
</when>
<when test="lastName != null">
AND last_name = #{lastName}
</when>
<when test="gender != null">
AND gender = #{gender}
</when>
<when test="email != null">
AND email = #{email}
</when>
<otherwise>
AND 1 = 1
</otherwise>
</choose>
</select>

  2、EmployeeMapper接口中,新增方法

 public List<Employee> testConditionChoose(Employee employee);

  3、测试方法  

 @Test
public void test002() throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sessionFactory.openSession(); try {
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> list = mapper.testConditionChoose(new Employee(1, null, null, null));
System.out.println(list.size());
for (Employee employee : list) {
System.out.println(list);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}

  4、执行结果

    

where

  where标签:用于编写带where条件的sql,配合if标签使用,它会自动去除首个AND前缀。

  示例

  1、EmployeeMapper新增Sql如下:

 <!-- if + where -->
<select id="testConditionIfWhere"
resultType="com.hd.test.pojo.Employee">
select id, last_name lastName, gender from employee
<where>
<if test="id != null">
AND id = #{id}
</if>
<if test="lastName != null and lastName.trim() != ''">
AND last_name = #{lastName}
</if>
<if test="gender==0 or gender==1">
AND gender = #{gender}
</if>
<if test="email != null &amp;&amp; lastName!=&quot;&quot;">
AND email = #{email}
</if>
</where>
</select>

  2、EmployeeMapper接口中,新增方法

 public List<Employee> testConditionIfWhere(Employee employee);

  3、测试方法

 @Test
public void test003() throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sessionFactory.openSession(); try {
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> list = mapper.testConditionIfWhere(new Employee("小红", "1", null));
System.out.println(list.size());
for (Employee employee : list) {
System.out.println(list);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}

  4、执行结果

    

trim

  trim标签:可以去掉字符串的首尾字符串,以及在字符串前后添加前后缀

  示例

  1、EmployeeMapper新增Sql如下:

 <select id="testConditionIfTrim" resultType="com.hd.test.pojo.Employee">
select id, last_name lastName, gender from employee
<!-- 后面多出的and或者or where标签不能解决
prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。 prefix给拼串后的整个字符串加一个前缀
prefixOverrides="": 前缀覆盖: 去掉整个字符串前面多余的字符
suffix="":后缀 suffix给拼串后的整个字符串加一个后缀
suffixOverrides="" 后缀覆盖:去掉整个字符串后面多余的字符 -->
<trim prefix="where" prefixOverrides="AND">
<if test="id != null">
AND id = #{id}
</if>
<if test="lastName != null">
AND last_name = #{lastName}
</if>
<if test="gender != null">
AND gender = #{gender}
</if>
<if test="email != null">
AND email = #{email}
</if>
</trim>
</select> 

  2、EmployeeMapper接口中,新增方法

 public List<Employee> testConditionIfTrim(Employee employee); 

  3、测试方法

 @Test
public void test004() throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sessionFactory.openSession(); try {
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> list = mapper.testConditionIfTrim(new Employee(1, null, null, null));
System.out.println(list.size());
for (Employee employee : list) {
System.out.println(list);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}

  4、执行结果

    

    

foreach

  动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候

  示例

  1、EmployeeMapper新增Sql如下: 

 <!-- foreach -->
<select id="testConditionForeach" resultType="com.hd.test.pojo.Employee">
select id, last_name lastName, gender from employee
<!--
collection:指定要遍历的集合:
list类型的参数会特殊处理封装在map中,map的key就叫list
item:将当前遍历出的元素赋值给指定的变量
separator:每个元素之间的分隔符
open:遍历出所有结果拼接一个开始的字符
close:遍历出所有结果拼接一个结束的字符
index:索引。遍历list的时候是index就是索引,item就是当前值
遍历map的时候index表示的就是map的key,item就是map的值 #{变量名}就能取出变量的值也就是当前遍历出的元素
-->
<foreach collection="ids" item="id" separator="," open="where id in (" close=")" >
#{id}
</foreach>
</select>

  2、EmployeeMapper接口中,新增方法

 public List<Employee> testConditionForeach(@Param("ids")List<Integer> ids);

  3、测试方法

 @Test
public void test005() throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sessionFactory.openSession(); try {
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> list = mapper.testConditionForeach(Arrays.asList(1, 2, 3, 4));
System.out.println(list.size());
for (Employee employee : list) {
System.out.println(list);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}

  4、执行结果

    

set

  set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号

  示例

  1、EmployeeMapper新增Sql如下: 

 <!-- set -->
<update id="testConditionSet">
update employee
<set>
<if test="lastName != null">
last_name = #{lastName},
</if>
<if test="gender != null">
gender = #{gender},
</if>
<if test="email != null">
email = #{email},
</if>
</set>
where id = #{id}
</update> 

  2、EmployeeMapper接口中,新增方法

 public boolean testConditionSet(Employee employee);

  3、测试方法

 @Test
public void test006() throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sessionFactory.openSession(); try {
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
boolean f = mapper.testConditionSet(new Employee(1, "小白", "1", null));
System.out.println(f);
session.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}

  4、执行结果

    

bind

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

 <select id="testConditionBind" resultType="Blog">
<bind name="pattern" value="'%' + keyword + '%'" />
SELECT * FROM employee WHERE last_name LIKE #{pattern}
</select>

sql

  可以用来包含其他sql

 <sql id="selectSql">select id, last_name lastName, gender from employee</sql>

 <select id="testConditionInclude" resultType="com.hd.test.pojo.Employee">
<include refid="selectSql"></include>
where id = 1
</select>

Mybatis中2个内置参数 _parameter和_databaseId

  示例

  1、EmployeeMapper新增Sql如下:

 <!-- 两个内置参数:
不只是方法传递过来的参数可以被用来判断,取值。。。
mybatis默认还有两个内置参数:
_parameter:代表整个参数
单个参数:_parameter就是这个参数
多个参数:参数会被封装为一个map;_parameter就是代表这个map _databaseId:
如果配置了databaseIdProvider标签。 _databaseId就是代表当前数据库的别名mysql
如果没配置了databaseIdProvider标签。 _databaseId为null
-->
<select id="testInnerParameter" resultType="com.hd.test.pojo.Employee">
<if test="_databaseId == 'mysql'">select * from ${_parameter}</if>
<if test="_databaseId != 'mysql'">select * from ${_parameter} where 1 = 1</if>
</select>

  2、mybatis-config.xml中的配置

 <databaseIdProvider type="DB_VENDOR">
<!-- 为不同的数据库厂商起别名 -->
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
<property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>

  3、EmployeeMapper接口中,新增方法 

 public List<Employee> testInnerParameter(String tableName);

  4、测试方法

 @Test
public void test007() throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sessionFactory.openSession(); try {
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> list = mapper.testInnerParameter("employee");
System.out.println(list.size());
for (Employee employee : list) {
System.out.println(employee);
} } catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}

  5、执行结果,从执行结果可以看出,_parameter == employee 参数,_databaseId == mysql 数据库别名

    

【Mybatis】MyBatis之动态SQL(六)的更多相关文章

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

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

  2. Mybatis入门之动态sql

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

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

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

  4. mybatis中的动态SQL

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

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

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

  6. MyBatis实战之动态SQL

    如果使用JDBC或者其他框架,很多时候你得根据需要去拼接SQL,这是一个麻烦的事情,而MyBatis提供对SQL语句动态的组装能力,而且它只有几个基本的元素,非常简单明了,大量的判断都可以在MyBat ...

  7. 6.Mybatis中的动态Sql和Sql片段(Mybatis的一个核心)

    动态Sql是Mybatis的核心,就是对我们的sql语句进行灵活的操作,他可以通过表达式,对sql语句进行判断,然后对其进行灵活的拼接和组装.可以简单的说成Mybatis中可以动态去的判断需不需要某些 ...

  8. MyBatis注解配置动态SQL

    MySQL创建表 DROP TABLE IF EXISTS `tb_employee`; CREATE TABLE `tb_employee` ( `id` int(11) NOT NULL AUTO ...

  9. mybatis框架(5)---动态sql

    那么,问题来了: 什么是动态SQL? 动态SQL有什么作用? 传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误.Mybatis的动态S ...

  10. MyBatis进阶使用——动态SQL

    MyBatis的强大特性之一就是它的动态SQL.如果你有使用JDBC或者其他类似框架的经验,你一定会体会到根据不同条件拼接SQL语句的痛苦.然而利用动态SQL这一特性可以彻底摆脱这一痛苦 MyBati ...

随机推荐

  1. 11Linux_sshd_Apache

    1.Linux系统中一切都是文件. 2.配置服务实际上就是在修改配置文件. 3.重启相应服务来加载最新的配置参数. 4.为了保证下次还生效,加入到开机启动项中.

  2. Winform 中写代码布局中遇到的控件遮盖问题

    在winform中编程时,需要动态向主窗体中增加菜单栏和用户控件,菜单栏需要设置DockStyle为Top ,而设置用户控件的DockStyle为Fill,之后在加载的时候,出现了菜单栏遮盖用户控件的 ...

  3. docker php容器中简单添加seaslog拓展

    最近有个项目用到了seaslog,因为之前调试php的容器已经搭好了,不想再通过dockerfile重新搭建了,搜了半天没有东西可以装,就仿照着安装redis拓展操作了一顿 1.wget http:/ ...

  4. 浏览器端时间循环与nodejs端时间循环的不同之处(宏任务与微任务)

    浏览器端与node端都有宏任务与微任务的概念.字面意思上看宏任务就是耗时间比较长的任务,而微任务是耗时短的任务. 在浏览器端,宏任务包括setTimeout,setInterval,微任务则包括Pro ...

  5. SQL Server 2016 在Windows Server 2012 R2 上的初步安装与远程连接实战(一):初步配置

    1.安装过程没有什么说头 2.下载并安装SSMS(SQLServer Management Studio),目前已更新到2017.1 3.使用SSMS登陆数据库 第一次选择Windows 身份验证,可 ...

  6. getBoundingClientRect获取元素在页面上的位置

    getBoundingClientRect用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置. getBoundingClientRect是DOM元素到浏览器可视范围的距离(不包含文档卷起 ...

  7. setCapture 使用方法

    setCapture 可以捕获到 移动到浏览器外的鼠标事件. 例如拖动过程中,即使鼠标移动到了浏览器外,拖动程序依然可以执行! 作用就是把 把鼠标事件 捕获到 当前文档指定的对象! setCaptur ...

  8. 搭建redis-sentinel(哨兵机制)集群

    redis怎么才能做到高可用 对于redis主从架构,slave可以对应多个本身可以保障高可用,但是对于一个master节点,如果宕机,整个缓存系统就无法进行写的操作,显然整个系统会无法做到高可用 s ...

  9. React—Native开发之 Could not connect to development server(Android)解决方法

    作为初学者昨天还好好能跑的项目今天就会遇到突然爆红出错是经常的事,让我们来看下是什么错吧 先来翻译: 连接不到开发的服务器. 请按照以下的步骤来修复此问题: 确保包服务器在运行确保你的设备或者模拟器连 ...

  10. phpstorm中open in browser端口和路径设置

    phpstorm默认的端口号是:63342但是我装的apache服务器的默认端口是80网上查找资料,都说可以加listen的端口,比如这里 #Listen 12.34.56.78:80Listen 8 ...