Mybatis-动态SQL-trim-choose-foreach
动态SQL
官方文档已经写的非常详细
动态Sql是指根据不同的条件生成不同的SQL语句
之前是手动拼接的,拼接sql语句是很麻烦的
四个标签:
- if
- choose(when,oherwise)
- trim(where,set)
- foreach
动态SQL环境搭建
- 数据库
- maven导包
- 实体类
- Mapper.xml
- 核心配置文件
- setting驼峰命名转换
- 工具类
- IDutils通过UUID实现随机ID
都是比较常用的套路
开始
创建数据库
Maven导包
<dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency> </dependencies>
编写POJO实体类
@Data @NoArgsConstructor @Alias("Blog") public class Blog {private String id;private String title;private String author;private Date createTime;//添加驼峰命名映射setting/*这个名字会映射成create_time*//*mapUnderscoreToCamelCase*/private int views; }
编写接口以及接口映射
编写好实体类就写好对应的接口,接口写好写映射,然后把映射添加到核心配置文件中去
public interface blogMapper {@Select("select * from blog")List<Blog> getblogs();int addBook(Blog blog); }
暂时写了两个接口,一个使用注解一个使用xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.haoyun.dao.blogMapper"><insert id="addBook" parameterType="Blog">insert into mybatis.blog (id,title,author,create_time,views)values (#{id},#{title},#{author},#{createTime},#{views});</insert></mapper>
因为添加了驼峰命名的设置,所以这里传递参数是填写的createTime
编写核心配置文件
使用的是外部配置文件
driver = com.mysql.cj.jdbc.Driver url= jdbc:mysql://localhost:3306/mybatis?useSSL=false -TRUE&useUnicode=true&characterEncoding=UTF-8 username =root password = 123456
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><!--引入外部配置文件--><properties resource="db.properties"/><settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><package name="com.haoyun.POJO"/></typeAliases><!--可以写多套环境配置,s复数,可以编写多套配置环境,但是default只能选择一套 --><environments default="Test"><!--这样就会选择Test的环境配置--><environment id="Test"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><!--映射--><mappers><mapper class="com.haoyun.dao.blogMapper"/><mapper resource="blogMapper.xml"/></mappers></configuration>
要注意setting标签编写的位置
设置 mapUnderscoreToCamelCase为true,名字不要打错
https://mybatis.org/mybatis-3/zh/configuration.html#settings
编写工具类
MybatisUtil这个工具类使用过好多次了,用来创建sqlsession
public class MybatisUtil {private static SqlSessionFactory sqlSessionFactory = null;static {InputStream inputStream = null;try {inputStream = Resources.getResourceAsStream("mybatis-config.xml");} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}public static SqlSession getSqlSession(){return sqlSessionFactory.openSession();} }
再写一个随机生成ID的,使用UUID方法
public class IDutils {public static String getId(){return UUID.randomUUID().toString().replaceAll("-","");} }
将 “-” 替换为 “” 空
1a19b16580bb46588863d96fa4822d4f测试得到的id
环境整体结构
测试
public class blogTest {@Testpublic void Test() {SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);List<Blog> getblogs = mapper.getblogs();for (Blog getblog : getblogs) {System.out.println(getblog);}sqlSession.close();}@Testpublic void TestInsert() {SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);Blog blog = new Blog();blog.setId(IDutils.getId());blog.setTitle("TestTitle");blog.setAuthor("TestAuthor");//生成时间记得选择util包的Dateblog.setCreateTime(new Date());blog.setViews(1200);mapper.addBook(blog);sqlSession.commit();sqlSession.close();}@Testpublic void IDutilsTest() {System.out.println(IDutils.getId());}}
动态SQL之IF语句
就是再Mapper.xml中添加if判断,实现sql的拼接,可以判断是否传递了对应列的参数来指定拼接对应的sql
流程:
添加接口方法
设置mapper.xml
- 加入if判断
测试
添加接口发方法
List<Blog> queryBlogIF(Map map);
设置mapper.xml
<select id="queryBlogIF" parameterType="map" resultType="Blog">select * from blog<where><if test="title!= null">and title = #{title}</if><if test="author != null">and author =#{author}</if></where></select>
参数类型为map,返回值类型为Blog,这个添加了重命名
为了保证if条件都不符合,不进行拼接sql语句的情况,不能写成这样,这样拼接上是直接跟着and或or的,所以在if外要包上一层
select * from blog where
如果传递了参数,进行判断,然后拼接sql
测试
@Test public void queryBlogIFTest(){SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);HashMap hashMap = new HashMap();hashMap.put("title","sadfasdf");hashMap.put("author","l");List<Blog> blogs = mapper.queryBlogIF(hashMap);for (Blog blog : blogs) {System.out.println(blog);}sqlSession.close();}
结果
可以选择传入一个空的hashMap,查询的就是全表的信息
trim(where,set)
trim 切除
这个主要的功能就是,拼接字符串,然后删除语句后缀的逗号
<select 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}
</select>
根据编写内容不同选择不同的标签,这里是更新,所以加入了set标签,使用方法也是一样的,只是这里拼接到where的时候会取除末尾的标签中语句的逗号,当然,两个if都没用上,会直接报错的,因为set之后直接拼接where,造成语法错误
@Test
public void queryBlogIFTest(){SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);HashMap hashMap = new HashMap();hashMap.put("title","sadsdf");hashMap.put("author","test");hashMap.put("id","1");mapper.updateBlog(hashMap);sqlSession.commit();sqlSession.close();
}
最后author末尾的逗号是被消除了
choose(when,otherwise )
choose 选择
when 什么情况下
otherwise 否则
规则有点像switch,只去匹配case中的一个值,唯一不同的就是otherwise必须添加参数,如果走了where就不会走otherwise,where都没走就会走otherwise,执行顺序是从上往下执行的,先判定上面的where
choose语句
<select id="queryBlogChoose" parameterType="map" resultType="Blog">select * from blog<where><choose><when test="title != null">and title = #{title}</when><when test="author!= null">and author = #{author}</when><otherwise>and views = #{views}</otherwise></choose></where></select>
多种情况测试
不填参数
@Test public void queryBlogIFTest(){SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);HashMap hashMap = new HashMap();//hashMap.put("title","sadfasdf");//hashMap.put("author","l");//hashMap.put("views","55");List<Blog> blogs = mapper.queryBlogChoose(hashMap);for (Blog blog : blogs) {System.out.println(blog);}sqlSession.close(); }
自动的添加了views条件但是parameter为null
没查询出来
hashMap.put("views",10);
所以前面的when没有参数就会添加otherwise中的语句
加入中间when值
hashMap.put("author","l"); hashMap.put("views",10);
加入了中间的author when判断和otherwise判断
但是只执行了when的语句,otherwise并没有执行
when优先级
hashMap.put("title","sadfasdf"); hashMap.put("author","l"); hashMap.put("views",10);
三条都加入了
但是只执行了第一条
所以第一条的优先级最高
总结:
- 什么参数都不加的情况下会选择otherwise中的语句
- 第一个多条when条件,从上往下判断,执行排在上面的
- 只选择一条,包括otherwise
共同的父亲trim
如果前置有set关键字,就会删除无关的逗号,prefix 前缀
指定的是一个where,如果存在就会删除指定的内容
这是定制化sql用的一些东西
SQL片段
有一些重复的语句,可以提取出代码片段,实现sql语句的复用
<sql id="if_title_author"><if test="title!= null">and title = #{title}</if><if test="author != null">and author =#{author}</if>
</sql><select id="queryBlogIF" parameterType="map" resultType="Blog">select * from blog<where><include refid="if_title_author"/></where>
</select>
最好sql片段不要编写太复杂的事情,要不然重用效率就变低了
不要存在where标签,where是要根据条件语句来查询的加入就不好实现复用
foreach
<select id="queryBlogForEach" parameterType="map" resultType="Blog">select * from blog<where><foreach collection="ids" item="id" open="and (" close=")" separator="or">id = ${id}</foreach></where>
</select>
传入一个map类型参数,返回值是一个Blog类型
collection 传递进一个集合,集合的名称为ids,那么用map传递参数的时候就要对应ids名进行传参
里面的每个元素是id,传递了集合就会进行自动的遍历集合,传递参数进id中,
open开始,加入where是为了解决select * from where 1=1 后面必须跟指定条件成立的语句,要不然动态sql没有进入foreach就会变成 select * from where 导致语句错误,加入where标签,还能根据判断去除不必要的and或or
这里就是open开始,填装了一个and (,注意,and和( 之间是有一个空格的,要不然where会识别不出来
在日志中查看得出的结果就是这样
本来用来连接其他条件的语句,不连接其他条件,and没有被去除,导致语句出错
close foreach结束时添加
separator 分隔符,用来分隔集合中元素的分隔符
最后给集合元素传参
@Test
public void queryBlogForEachTest(){SqlSession sqlSession = MybatisUtil.getSqlSession();blogMapper mapper = sqlSession.getMapper(blogMapper.class);HashMap hashMap = new HashMap();ArrayList<String> arrayList = new ArrayList<String>();arrayList.add("1");arrayList.add("2");arrayList.add("3");hashMap.put("ids",arrayList);List<Blog> blogs = mapper.queryBlogForEach(hashMap);for (Blog blog : blogs) {System.out.println(blog);}sqlSession.commit();sqlSession.close();
}
总结:
动态sql,本质还是sql,只是在sql层面,去执行一个逻辑代码,按照sql格式进行拼接,排列组合,去除不必要的字符
先在Mysql中写出完整的sql,再去修改实现动态sql,实现通用
多去看官方文档
怎么使用普通的sql查询还是不够的,需要多去了解更深层次的知识
- mysql引擎
- InnoDB底层原理
- 索引
- 索引优化
Mybatis-动态SQL-trim-choose-foreach相关推荐
- MyBatis动态SQL之<foreach>用法
目录 一.foreach元素的属性 二.collection属性值的三种情况 三.代码示例 四.相关错误 一.foreach元素的属性 collection: foreach的对象,作为入参,对象为l ...
- MyBatis动态sql之choose(when、otherwise)用法
if标签是与(and)的关系,只要test中的表达式为 true,就会执行 if 标签中的条件;而 choose 是或(or)的关系,并不想应用所有的条件,而只是想从多个选项中选择一个. choose ...
- Mybatis动态sql中的foreach标签的使用
foreach 标签一般用于遍历集合,构建in条件语句或者批量操作语句 <insert id="batchSave" parameterType="java.uti ...
- MyBatis动态SQL之 set 和 trim标记的使用示例
2019独角兽企业重金招聘Python工程师标准>>> 和之前的where一样,set和trim也是智能标记 在之前的user.xml中添加 <update id=" ...
- MyBatis动态SQL(认真看看, 以后写SQL就爽多了)
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:cnblogs.com/homejim/p/9909657. ...
- 9.mybatis动态SQL标签的用法
mybatis动态SQL标签的用法 动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦 ...
- 认真看看, 以后写 SQL 就爽多了:MyBatis 动态 SQL:
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 阿进的写字台 来源 | cnblogs.com ...
- MyBatis动态SQL,写SQL更爽
点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!个人原创100W +访问量博客: ...
- 认真看看, 以后写 SQL 就爽多了:MyBatis 动态 SQL
点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达今日推荐:2020年7月程序员工资统计,平均14357元,又跌了,扎心个人原创100W+访问量博客:点击前往,查看更多 整理 ...
- Mybatis 动态Sql语句《常用》
MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格,还要注意省掉 ...
最新文章
- WEB标准页面CSS命名参考
- go 获取内核个数_图解Go运行时调度器
- python爬虫今日头条街拍美图开发背景_分析Ajax请求并抓取今日头条街拍美图:爬取详情页的url与实际页面上显示不符...
- 《社交网站界面设计(原书第2版)》——2.11 提问
- mysql 迁移到tidb_通过从MySQL迁移到TiDB来水平扩展Hive Metastore数据库
- 02-Django基础知识
- Java基础复习——访问权限
- mysql 参数 innodb_flush_log_at_trx_commit
- linux dns服务无效,Linux下搭建DNS服务器及踩坑
- 本地运行 MAYA 帮助文档
- 两种“新型”的javaweb后门(jspx和Java Logger)
- WeaveSocket框架-Unity太空大战游戏-通信协议-2
- 阿里云IoT千里传音之声连网互动营销服务,首次亮相!
- 2021年最新Android面试点梳理,成功入职腾讯
- 百度人脸识别API调用实现
- live.com与live.cn邮箱收不到QQ绑定激活信的解决方法
- word右顶格_word顶格书写 WORD如何顶格
- eclipse配置python解析器_Eclipse中配置Python环境
- D. Equalize Them All
- imx6 添加matrix keypad