mybatis-动态SQL

理解:在SQL层面中,可以使用一些逻辑代码,动态的拼接SQL,根据不同的条件,执行不同的SQL语句

1 准备阶段

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

1.2 引入依赖

1.3 编写配置文件 mybatis-config.xml 和属性文件 db.properties

1.4 编写工具类 

1.4.1 MybatisUtils : 用来获取 SqlSession

1.4.2 IdUtils : 使用 UUID 生成 不重复的Id

public static String getId(){
return UUID.randomUUID().toString().replaceAll("-","");
}

1.5 编写 javaBean

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

1.5.1 解决属性名和字段名不一致的问题

在 mybatis-config.xml 的 settings 中 配置一条 setting

<!--是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。-->
<setting name="mapUnderscoreToCamelCase" value="true"/>

1.6 编写 BlogMapper 接口

1.7 编写对应 BlogMapper 接口 对应的 BlogMapper.xml 文件

2 插入数据

2.1 在 BlogMapper 中添加方法

//插入数据
int addBlog(Blog blog);

2.2 在 BlogMapper.xml 中编写对应的SQL

<insert id="addBlog" parameterType="blog">
insert into blog (id,title,author,create_time,views)
values(#{id},#{title},#{author},#{createTime},#{views});
</insert>

2.3 在测试类中执行

@Test
public void addBlog(){
SqlSession session = MybatisUtils.getSqlSession();
BlogMapper mapper = session.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);
session.close();
}

3 if

3.1 在 BlogMapper 中添加方法

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

3.2 在 BlogMapper.xml 中编写对应的SQL

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

3.3 测试

@Test
public void queryBlogIf(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap<>();
map.put("title","Spring如此简单");
map.put("author","呵呵哒");
List<Blog> blogList = mapper.queryBlogIf(map);
for (Blog blog : blogList) {
System.out.println(blog);
}
sqlSession.close();
}

3.4 执行结果

3.5 注

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

4 choose 

4.1 在 BlogMapper 中添加方法

List<Blog> queryBlogChoose(Map map);

4.2 在 BlogMapper.xml 中编写对应的SQL

<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.3 测试

@Test
public void queryBlogChoose(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
map.put("title","Spring如此简单");
map.put("author","呵呵哒");
map.put("views","9999");
List<Blog> blogList = mapper.queryBlogChoose(map);
for (Blog blog : blogList) {
System.out.println(blog);
}
sqlSession.close();
}

4.4 执行结果

4.5 注

choose 相当于 Java 中的 switch 语句,只能从多个条件当中,选择一个执行

5 set

5.1 在 BlogMapper 中添加方法

//更新博客
int updateBlog(Map map);

5.2 在 BlogMapper.xml 中编写对应的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>

5.3 测试

@Test
public void updateBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
map.put("id","f09397b615464b72ac6a01c8662edac7");
map.put("title","CNM");
map.put("author","SB");
mapper.updateBlog(map);
sqlSession.close();
}

5.4 执行结果

5.5 注

set  可以将动态的配置 SET 关键字,并剔除追加到条件末尾的任何不相关的逗号

6 sql片段

6.1 提取 sql 片段

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

6.2 引用 sql 片段

<include refid="if-title-author"></include>

6.3 注

  1. 引用 sql 片段,如果refid 指定的SQL片段不在本文件中,那么需要在前面加上 namespace 
  2. 最好基于单表来定义 sql 片段,提高片段的可重用性
  3. 因为 where 包含的代码块 是动态的 所以 在 sql 片段中不要包括 where

7 foreach

7.1 在 BlogMapper 中添加方法

//查询前三条记录的博客
List<Blog> queryBlogForeach(Map map);

7.2 在 BlogMapper.xml 中编写对应的SQL

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

7.3 测试

@Test
public void queryBlogForeach(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
ArrayList<Object> ids = new ArrayList<>();
ids.add("f09397b615464b72ac6a01c8662edac7");
ids.add("f6250c4c1d49440a9da1dcaacc782dd3");
ids.add("5b6b0356a414490f8e1a133074458e8c");
Map map = new HashMap();
map.put("ids",ids);
mapper.queryBlogForeach(map);
sqlSession.close();
}

7.4 执行结果

7.5 注

  1. collection 相当于要遍历的集合
  2. item 进行迭代的集合中的元素,如果是键值对,则代表 key - value 里的 value
  3. open 该拼接语句以什么开始
  4. close 该拼接语句以什么结束
  5. separator 拼接语句中每个元素中间的以什么分割
  6. index 表示索引,如果是键值对,则代表 key - value 里的 key

8 trim

8.1 自定义拼接效果,包括去除多余的关键字和符号,或者拼接 where, set 关键字等等,可用于选择性插入、更新、删除或者条件查询等操作.prefix    给sql语句拼接的前缀

8.2 关键字

  1. suffix : 给sql语句拼接的后缀
  2. prefixOverrides : 去除sql语句前面的关键字或者字符,该关键字或者字符由prefixOverrides属性指定,假设该属性指定为"AND",当sql语句的开头为"AND",trim标签将会去除该"AND"
  3. suffixOverrides : 去除sql语句后面的关键字或者字符,该关键字或者字符由suffixOverrides属性指定
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示