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 注
- 引用 sql 片段,如果refid 指定的SQL片段不在本文件中,那么需要在前面加上 namespace
- 最好基于单表来定义 sql 片段,提高片段的可重用性
- 因为 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 注
- collection 相当于要遍历的集合
- item 进行迭代的集合中的元素,如果是键值对,则代表 key - value 里的 value
- open 该拼接语句以什么开始
- close 该拼接语句以什么结束
- separator 拼接语句中每个元素中间的以什么分割
- index 表示索引,如果是键值对,则代表 key - value 里的 key
8 trim
8.1 自定义拼接效果,包括去除多余的关键字和符号,或者拼接 where, set 关键字等等,可用于选择性插入、更新、删除或者条件查询等操作.prefix 给sql语句拼接的前缀
8.2 关键字
- suffix : 给sql语句拼接的后缀
- prefixOverrides : 去除sql语句前面的关键字或者字符,该关键字或者字符由prefixOverrides属性指定,假设该属性指定为"AND",当sql语句的开头为"AND",trim标签将会去除该"AND"
- suffixOverrides : 去除sql语句后面的关键字或者字符,该关键字或者字符由suffixOverrides属性指定
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术