MyBatis——(三)动态SQL

2018-11-28 20:43:00     

一、摘要

前几篇博客介绍的sql语句都是较简单的单条件查询语句。要是遇到复杂的多条件,往往需要拼接,而拼接 SQL ,稍微不注意,由于引号,空格等缺失可能都会导致错误。

那么怎么去解决这个问题呢?这就是本篇所讲的使用 mybatis 动态SQL,通过 if, where, set, trim, when, choose, otherwise, foreach,bind等标签,可组合成非常灵活的SQL语句,从而在提高 SQL 语句的准确性的同时,也大大提高了开发人员的效率。

二、动态SQL

新建一张老师表(teacher),插入三条数据

CREATE TABLE `teacher` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;


INSERT INTO `teacher` VALUES ('1', '数学老师');
INSERT INTO `teacher` VALUES ('2', '语文老师');
INSERT INTO `teacher` VALUES ('3', '英语老师');

多条件查询,通过id以及name查询:

<!-- map对象作为参数传递进去 -->
<select id="selectByIdAndName" parameterType="map" resultType="Teacher">
	select * from teacher where id>#{id} and name like concat('%',#{name},'%')
</select>

if标签

如果传入的name参数为空,那查询出来的结果就为空,显然我们不希望。我们希望的是如果name参数为空,那就只保留id为条件就好了,name条件去除。针对这个问题,mybatis引入了<if>标签来解决这个问题,如下代码:

<!-- map对象作为参数传递进去 -->
<select id="selectByIdAndName" parameterType="map" resultType="Teacher">
	select * from teacher 
	<if test="id != null">
		where id>#{id}
	</if>
	<if test="name != null">
		and name like concat('%',#{name},'%')
	</if>
</select>

where标签

但是如果id为空,name不为空呢?运行发现sql语句报错,这条sql语句变了select * from teacher and name like concat('%',#{name},'%')显然这是一条错误的sql语句,针对这个问题,mybatis引入了<where>标签来解决这个问题,如下代码:

<!-- map对象作为参数传递进去 -->
<select id="selectByIdAndName" parameterType="map" resultType="Teacher">
	select * from teacher
	<where>
		<if test="id != null">
			id>#{id}
		</if>
		<if test="name != null">
			and name like concat('%',#{name},'%')
		</if>
	</where>
</select>

如果<if>标签有(true)返回值时,则自动插入一个where。如果<if>标签无(false)返回值,则自动去除多出来的and或者or

set标签

更新操作中使用<set>标签

<update id="updateById" parameterType="Teacher">
	update teacher 
	<set>
		<if test="id != null">
			id=#{id},
		</if>
		<if test="name != null and name != ''">
			name=#{name}
		</if>
	</set>
	where id=#{id}
</update>

trim标签

trim标记是一个格式化的标记,可以完成set或者是where标记的功能,可以定制想要的功能。如下分别代替<where>标签和<set>标签

<!-- 代替where标签 -->
<select id="selectByTrim" parameterType="map" resultType="Teacher">
	select * from teacher
	<trim prefix="where" prefixOverrides="and | or">
		<if test="id != null">
			id>#{id}
		</if>
		<if test="name != null">
			and name like concat('%',#{name},'%')
		</if>
	</trim>
</select>

<!-- 代替set标签 -->
<update id="updateByTrim" parameterType="Teacher">
	update teacher
	<trim prefix="set" suffixOverrides=",">
		<if test="id != null">
			id=#{id},
		</if>
		<if test="name != null and name != ''">
			name=#{name}
		</if>
	</trim>
	where id=#{id}
</update>

prefix是代替标签,prefixoverride代表前缀,这里去掉该语句前面的and或者是or,suffixOverrides代表后缀,这里去掉该语句后面的,逗号

when choose标签

Mybatis里面没有if...else标签,但是可以使用when otherwise标签来达到这样的效果

<select id="selectByChoose" parameterType="map" resultType="Teacher">
	select * from teacher
	<where>
		<choose>
			<when test="name != null">
				and name like concat('%',#{name},'%')
			</when>
			<otherwise>
				and id>#{id}
			</otherwise>
		</choose>
	</where>
</select>

foreach标签

<foreach>标签主要用于构建in条件,他可以在sql中对集合进行迭代。通常用于批量删除、批量添加操作

<delete id="deleteByForeach">
	delete from teacher where id in
	<foreach collection="array" item="id" index="index" open="(" close=")" separator=",">
		#{id}
	</foreach>
</delete>

这里设定int[] array = {1,2,3},那么array将以数组的形式传递,这里的sql语句就是 delete from teacher where id in (1,2,3)

  • collection :collection属性的值有三个分别是list、array、map三种,分别对应的参数类型为:List、数组、map集合,我在上面传的参数为数组,所以值为array
  • item : 表示在迭代过程中每一个元素的别名
  • index :表示在迭代过程中每次迭代到的位置(下标)
  • open :前缀
  • close :后缀
  • separator :分隔符,表示迭代时每个元素之间以什么分隔

bind标签

<bind>标签就像是再做一次字符串拼接,方便后续使用。例如:模糊查询在MySql和Oracle是不一样的语句,使用<bind>标签就可以满足使用同一条语句既能在MySql上使用,也能在Oracle上使用。

<!-- bind标签 -->
<select id="listByBind" resultType="Teacher">
	<bind name="likename" value="'%' + name + '%'"/>
	select * from teacher where name like #{likename}	
</select>
ps:本篇博客源码下载链接:https://pan.baidu.com/s/1uxsGiOYpnhb0kC9VhK8YQA密码:tdrk
MyBatis——(二)一对多 多对一 多对多

一、摘要表和表之间的关系,常见的有一对多,多对一,多对多。比如教室表(classroom)和学生表(student)是有关系的,那么如何分析他们之间的关系呢? 一个学生(student)只能对应一间教室(classroom)一间教室(classroom)可以对应多个学生(student)所以教室(classroom)对学生(student)就是一对多,学生(student)对教室(classroom)就是多对一引入一个老师表(teacher),那老师表(teacher)和学生表(student)的关系是怎样的呢? 一个老师(teacher)可以对应多个学生(student) 一个学生(student)可以对应多个老师(teacher) 所以学生(student)对老师(teacher)就是多对多 二、一对多

MyBatis——(四)分页 c3p0连接池

PageHelper是一款犀利的Mybatis分页插件,使用了这个插件之后,分页开发起来更加简单容易。C3P0连接池会根据你的配置来初始化N个数据库连接,空闲时间后连接过期又会自动新建K个连接使得连接池总有空闲的数据库连接等待被取用。我们只需通过dataSourse.getConnection() 即可从线程池中取用一个已经连接好的空闲连接,执行数据库操作。然后“断开”(放回)这个连接,把这个连接的使用权放回连接池。

 发表评论