动态SQL
-
动态SQL
-
1. 搭建环境
-
2. IF
- 1. 编写接口
- 2. 编写mapper文件
- 3. 测试
- 3. choose(when,otherwise)
-
4. tirm(where,set)
- 1. where
- 2. set
-
3. trim
- 1. 与where等价的trim
- 2. 与set等价的trim
- 5. Foreach
-
6. SQL片段
- 1. 使用sql标签抽取公共的部分
- 2. 在需要使用的地方使用include标签引用即可
- 3. 注意事项
- 7. 动态SQL的本质
- 8. 总结
什么是动态SQL: 根据不同的条件生成不同的SQL语句
1. 搭建环境
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;
2. 创建一个基础工程
-
导包
-
编写配置文件
-
编写实体类
package com.wang.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Blog {
private int id;
private String title;
private String author;
//日期用util包中的
private Date createTime;
private int views;
}
-
编写实体类对应Mapper接口和对应的xml文件
-
插入数据
-
创建一个工具类,利用UUID作为数据库的id
package com.wang.utils;
import java.util.UUID;
public class IdUtils {
public static String getId() {
return UUID.randomUUID().toString().replaceAll("-","");
}
}
-
编写插入数据的接口及对应的mapper
package com.wang.dao;
import com.wang.pojo.Blog;
public interface BlogMapper {
//插入数据
int addBlog(Blog blog);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wang.dao.BlogMapper">
<insert id="addBlog" parameterType="Blog">
insert into blog(id,title,author,create_time,views)
values (#{id},#{title},#{author},#{createTime},#{views});
</insert>
</mapper>
-
插入数据
package com.wang.dao;
import com.wang.pojo.Blog;
import com.wang.utils.IdUtils;
import com.wang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.Date;
public class MyTest {
@Test
public void TestAddBlog() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = new Blog();
blog.setId(IdUtils.getId());
blog.setTitle("Mybatis");
blog.setAuthor("狂神说");
blog.setCreateTime(new Date());
blog.setViews(9999);
mapper.addBlog(blog);
blog.setId(IdUtils.getId());
blog.setTitle("Java");
mapper.addBlog(blog);
blog.setId(IdUtils.getId());
blog.setTitle("Spring");
mapper.addBlog(blog);
blog.setId(IdUtils.getId());
blog.setTitle("微服务");
mapper.addBlog(blog);
//增删改查要开启事务
sqlSession.commit();
sqlSession.close();
}
}
2. IF
1. 编写接口
//查询博客
List<Blog> queryBlogIF(Map map);
2. 编写mapper文件
<select id="queryBlogIF" parameterType="map" resultType="Blog">
select * from blog where 1 = 1
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
3. 测试
@Test
public void TestQueryBlogIF() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
map.put("author","狂神说");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
3. choose(when,otherwise)
类似Java中的switch语句,when相当于case,otherwise相当于default
<select id="queryBlogChoose" parameterType="map" resultType="Blog">
select * from blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
4. tirm(where,set)
1. where
由于使用where语句,如果第一个if不使用,则会在where后直接跟and,从而导致SQL语句报错
在之前的if标签中,使用了where 1 = 1来避免这种情况,但是这样写时不正规的
因此我们下面使用where标签来解决此问题
<select id="queryBlogIF" parameterType="map" resultType="Blog">
select * from blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。**
2. set
使用set标签解决update只更新部分字段导致出现无关的逗号导致SQL报错
<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>
3. trim
如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能
1. 与where等价的trim
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
2. 与set等价的trim
<trim prefix="SET" suffixOverrides=",">
...
</trim>
5. Foreach
<!--我们现在传递一个万能的map,这个map中可以存在一个集合
foreach中的collection标签为遍历的集合,item为集合中的元素
open为每一个遍历元素的对应语句的头开头,close为结尾
separator为其分隔符
-->
<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>
@Test
public void TestQueryBlogForeach() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
ArrayList<Integer> ids = new ArrayList<>();
for (int i = 1; i < 4; i++) {
ids.add(i);
}
map.put("ids",ids);
List<Blog> blogs = mapper.queryBlogForeach(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
6. SQL片段
有的时候,我们会将一些公共的部分抽取出来,方便复用
1. 使用sql标签抽取公共的部分
<sql id="if-title-author">
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
2. 在需要使用的地方使用include标签引用即可
<select id="queryBlogIF" parameterType="map" resultType="Blog">
select * from blog
<where>
<include refid="if-title-author">
</include>
</where>
</select>
3. 注意事项
- 最好基于单表来定义SQL片段
- 不要存在where标签
7. 动态SQL的本质
所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一个逻辑代码
8. 总结
- 动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了
- 建议:
- 先在MySQL中写出完整的SQL语句
- 再对应的去修改成为我们的动态SQL实现通用即可
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|