MyBatis笔记(六)
1. 动态SQL
1.1 介绍
概念:**动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句.*
官网描述:
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
-------------------------------
1.2 搭建环境
新建一个表:blog
CREATE TABLE `blog` (
`id` varchar(50) NOT NULL COMMENT '博客id',
`title` varchar(100) NOT NULL COMMENT '博客标题',
`author` varchar(30) NOT NULL COMMENT '博客作者',
`create_time` datetime NOT NULL COMMENT '创建时间',
`views` int(30) NOT NULL COMMENT '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插件IDUtil工具类
public class IDUtil {
public static String genId(){
return UUID.randomUUID().toString().replaceAll("-","");
}
}
编写实体类
public class Blog {
private String id;
private String title;
private String author;
private Date createTime;
private int views; // 无参构造
// 有参构造
// get、set、toString
}
编写Mapper接口及mapper配置文件
public interface BlogMapper {
int addBlog(Blog blog);
}
<?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="top.linzeliang.mapper.BlogMapper">
<insert id="addBlog" parameterType="blog">
insert into blog (id, title, author, create_time, views)
values (#{id},#{title},#{author},#{createTime},#{views});
</insert>
</mapper>
在MyBatis配置文件中设置下驼峰线自动转换
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--注册Mapper.xml-->
<mappers>
<mapper resource="top/linzeliang/mapper/BlogMapper.xml"/>
</mappers>
初始化博客方法
@Test
public void addInitBlog(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class); Blog blog = new Blog();
blog.setId(IDUtil.genId());
blog.setTitle("Mybatis如此简单");
blog.setAuthor("妙啊");
blog.setCreateTime(new Date());
blog.setViews(9999); mapper.addBlog(blog); blog.setId(IDUtil.genId());
blog.setTitle("Java如此简单");
mapper.addBlog(blog); blog.setId(IDUtil.genId());
blog.setTitle("Spring如此简单");
mapper.addBlog(blog); blog.setId(IDUtil.genId());
blog.setTitle("微服务如此简单");
mapper.addBlog(blog); session.close();
}
2. IF和WHERE语句
if语句就是判断是否满足某个条件,满足的话就添加标签内容到sql语句中where语句:如果包含的标签中含有返回值得话,他就会自动插入一个where,如果返回值的内容的第一个开头是and或者or,则会自动剔除
需求:根据作者名字和博客名字来查询博,如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名来查询
编写接口类
List<Blog> queryBlogIf(Map map);
编写对应的mapper配置文件
- 传入的参数是map,那么在if标签中直接写的是map中的key,不用加
#{}
<select id="queryBlogIf" resultType="blog" parameterType="map">
select *
from blog
<where>
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
- 传入的参数是map,那么在if标签中直接写的是map中的key,不用加
3. SET语句
- 如果在进行更新操作的时候,含有 set 关键词,则使用set标签,效果和
where也是一样的
编写接口方法
int updateBlog(Map map);
编写对应的mapper配置文件
<update id="updateBlog" parameterType="map">
update blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id = #{id}
</update>
4. CHOOSE语句
- 有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句
编写接口方法
List<Blog> queryBlogChoose(Map map);
编写对应的mapper配置文件
<select id="selectBlogChoose" resultType="blog" parameterType="map">
select *
from blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
adn views = #{views}
</otherwise>
</choose>
</where>
</select>
5. SQL片段
有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用
提取SQL片段:
<sql id="if-title-author">
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
引用SQL片段:
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
<include refid="if-title-author"></include>
<!-- 在这里还可以引用其他的 sql 片段 -->
</where>
</select>
最好基于 单表来定义 sql 片段,提高片段的可重用性
在 sql 片段中不要包括
where
6. ForEach
需求:我们需要查询 blog 表中 id 分别为1,2,3的博客信息
编写接口
List<Blog> queryBlogForeach(Map map);
编写对应的mapper配置文件
<select id="queryBlogForeach" parameterType="map" resultType="blog">
select * from blog
<where>
<!--
collection:指定输入对象中的集合属性
item:每次遍历生成的对象
open:开始遍历时的拼接字符串
close:结束时拼接的字符串
separator:遍历对象之间需要拼接的字符串
select * from blog where 1=1 and (id=1 or id=2 or id=3)
-->
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id = #{id}
</foreach>
</where>
</select>
总结:其实动态
sql语句的编写往往就是一个拼接的问题,为了保证拼接准确,我们最好首先要写原生的sql语句出来,然后在通过mybatis动态sql对照着改,防止出错
MyBatis笔记(六)的更多相关文章
- Mybatis笔记六:Mybatis中SqlSessionFactoryBuilder/SqlSessionFactory/SqlSession/映射器实例的作用域(Scope)和生命周期
SqlSessionFactoryBuilder 这个类可以被实例化.使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了.因此 SqlSessionFactoryBuilder ...
- Spring Boot 学习笔记(六) 整合 RESTful 参数传递
Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...
- 《MFC游戏开发》笔记六 图像双缓冲技术:实现一个流畅的动画
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9334121 作者:七十一雾央 新浪微博:http:/ ...
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- Learning ROS for Robotics Programming Second Edition学习笔记(六) indigo xtion pro live
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
- Python学习笔记六
Python课堂笔记六 常用模块已经可以在单位实际项目中使用,可以实现运维自动化.无需手工备份文件,数据库,拷贝,压缩. 常用模块 time模块 time.time time.localtime ti ...
- Mybatis笔记二:接口式编程
目录 旧方法的弊端 接口式编程 接口式编程的好处 接口式编程的增删改查 旧方法的弊端 在Mybatis笔记一中,我们使用命名空间+id的方式实现了Mybatis的执行,不过这里的命名空间是我们随便写的 ...
- Typescript 学习笔记六:接口
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Django开发笔记六
Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.登录功能完善 登录成功应该是重定向到首页,而不是转发 ...
- python3.4学习笔记(六) 常用快捷键使用技巧,持续更新
python3.4学习笔记(六) 常用快捷键使用技巧,持续更新 安装IDLE后鼠标右键点击*.py 文件,可以看到Edit with IDLE 选择这个可以直接打开编辑器.IDLE默认不能显示行号,使 ...
随机推荐
- react hooks useEffect 取消 promise
react hooks useEffect 取消 promise cancel promise https://github.com/facebook/react/issues/15006#issue ...
- Flutter: moor_flutter库,简化sqlite操作
入门 video moor_flutter 示例代码仓库 install dependencies: ... moor_flutter: dev_dependencies: ... moor_gene ...
- Flutter: Draggable和DragTarget 可拖动小部件
API class _MyHomeState extends State<MyHome> { List<Map<String, String>> _data1 = ...
- js字典
传送门https://www.2cto.com/kf/201709/680989.html 点击
- 阿里面试这样问:redis 为什么把简单的字符串设计成 SDS?
2021开工第一天,就有小伙伴私信我,还给我分享了一道他面阿里的redis题(这家伙绝比已经拿到年终奖了),我看了以后觉得挺有意思,题目很简单,是那种典型的似懂非懂,常常容易被大家忽略的问题.这里整理 ...
- 源码分析:CyclicBarrier 之循环栅栏
简介 CyclicBarrier 是一个同步辅助工具,允许一组线程全部等待彼此达到共同屏障点,且等待的线程被释放后还可以重新使用,所以叫做Cyclic(循环的). 应用场景 比如出去旅行时,导游需要等 ...
- JDK源码阅读-FileOutputStream
本文转载自JDK源码阅读-FileOutputStream 导语 FileOutputStream用户打开文件并获取输出流. 打开文件 public FileOutputStream(File fil ...
- TERSUS无代码开发(笔记09)-简单实例前端样式设计
前端常用样式设计 =========================================================================================== ...
- LeetCode-[list-of-depth-lcci]
特定深度节点链表-求解每一层二叉树从左到右遍历形成的链表 list-of-depth-lcci 这是关于二叉树的问题,遍历每一层的结点并且存在链表中. 可以采取队列类似于广度优先搜索的方法进行搜索.每 ...
- 如何在Bash脚本中引入alias
更多精彩内容,请关注微信公众号:后端技术小屋 alias的使用 在日常开发中,为了提高运维效率,我们会用alias(命令别名)来定义命令的简称.比如在~/.bash_profile中添加: alias ...