12.动态SQL

12.动态SQL

什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句

利用动态SQL这一特性可以彻底摆脱这种痛苦

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

12.1搭建环境

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

创建一个基础工程

  • 导包
  • 编写核心配置文件
  • 编写实体类

注意:java中创建实体类中的时间属性需选择.util,选择.sql不生效

 

@Data
public class Blog {
private int id;
private String title;
private String author;
private Date createTime;//属性名和字段名不一致
private int views;
}

如何解决属性名和字段名不一致:

在核心配置文件的Setting方法里加入如下代码:

<settings>
<!--开启驼峰命名转换-->
<setting name="mapUnderscoreToCamelCase" value="true "/>
</settings>
  • 编写工厂类(utils—sqlSessionFactory)
  • 编写实体类对应的Mapper接口和Mapper.xml文件

IF标签

BlogMapper

//查询博客
List<Blog> queryBlogIF(Map map);

BlogMapper.xml

<mapper namespace="com.itxiaofei.dao.BlogMapper">
<insert id="addBlog" parameterType="blog">
insert into mybatis.blog (id, title, author, create_time, views)
values(#{id},#{title}, #{author}, #{createTime}, #{views});
</insert>
<!--if标签是固定的格式-->
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog <!--where 1=1-->
<!--不使用where也可以在后面加where1=1,但是不正规-->
<where>
<if test="title != null">
and title like #{title}
</if>
<if test="author != null">
and author like #{author}
</if>
</where>
</select>
</mapper>

使用where标签的原因:(where 1=1不正规!)

测试:

//测试动态SQL中if
@Test
public void queryBlogIF(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
/*map.put("title","Java并不难");*/
map.put("author","if小飞");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}

choose (when, otherwise)标签

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

还是上面的例子,但是策略变为:传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG(这可能是管理员认为,与其返回大量的无意义随机 Blog,还不如返回一些由管理员精选的 Blog)。

1.BlogMapper

List<Blog> queryBlogChoose(Map map)

2.BlogMapper.xml

<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
and title like #{title}
</when>
<when test="author != null">
and author like #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>

3.测试

//测试动态SQL中choose (when, otherwise)标签
@Test
public void queryBlogChoose(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
map.put("views","9999");
/*map.put("title","Java并不难");*/
/*map.put("author","if小飞");*/
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}

trim、where、set标签

where标签:(自动去除“AND” 或 “OR”)

<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
and title like #{title}
</when>
<when test="author != null">
and author like #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>

set标签:(自动去除逗号)

<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>

set测试:

//测试动态SQL中的set标签
@Test
public void updateBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
//id后面的参数那么一长串是因为之前加了UUID防止数据太多导致重复
map.put("id","f125088b7dd74826a6b4eddc42132ad4");
map.put("title","Python并不难");
map.put("author","it小飞呀");
mapper.updateBlog(map);
sqlSession.close();
}

trim标签:

trim标签你可以理解为是set和where标签的整合

<!--prefix:前缀 ,prefixOverrides:前缀覆盖内容
suffix:后缀 ,suffixOverrides:后缀覆盖内容
-->
<trim prefix="" prefixOverrides="" suffix="" suffixOverrides="">
<!--写拼接的sql语句-->
</trim>

所谓的动态SQL,本质还是SQL,只是我们可以在SQL层面,去执行一个逻辑代码

Foreach(遍历)

 

 

1.编写接口

List<Blog> queryBlogForeach(Map map);

2.Foreach标签的使用

<!--Foreach标签
select * from blog where and(id=1 or id=2 or id=3)
下面Foreach标签的作用就是拼接这段话
我们传递一个万能的map,这个map中可以存在一个集合
-->
<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>

3.测试

//测试动态SQL中的Foreach标签
@Test
public void queryBlogForeach(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
//我们不知道到底有多少个数据元素的时候,就可使用ArrayList;<>里面放的是:泛型
//<>作用就是确定到底存放什么类型
// 如果知道数据集合有多少个元素,就用数组。
ArrayList<Integer> ids = new ArrayList<Integer>();
//Java Map.put()方法:获取Map集合的所有键名
map.put("ids",ids);
ids.add(1);
ids.add(2);
ids.add(3);
List<Blog> blogs = mapper.queryBlogForeach(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}

SQL片段

有些时候,我们可能会将一些公共的部分抽取出来,方便复用

1.使用sql标签抽取公共的部分

<sql id="if-title-author">
<if test="title != null">
and title like #{title}
</if>
<if test="author != null">
and author like #{author}
</if>
</sql>

2.在需要使用的地方使用Include标签引用即可

<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<include refid="if-title-author"></include>
</where>
</select>

动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了

建议:

  • 先在Mysql中写出完整的SQL,再对应去修改成为我们的动态SQL实现通用即可
posted @   It小飞呀  阅读(297)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示