Mybatis官方文档
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
数据库:
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
数据表对应的实体类:
package com.zyh.pojo;
import lombok.Data;
import java.util.Date;
@Data
public class Blog {
private String id;
private String title;
private String author;
private Date createime;
private int views;
}
实体类对应的接口:
package com.zyh.mapping;
import com.zyh.pojo.Blog;
public interface BlogMapper {
/**
* 插入数据
* @param blog
* @return
*/
int addBlog(Blog blog);
}
接口的BlogMapper.xml
配置
<mapper namespace="com.zyh.mapping.BlogMapper">
<insert id="addBlog" parameterType="Blog">
insert into mybatis.blog(id,title,author,create_time,views)
values (#{id},#{title},#{author},#{createTime},#{views});
insert>
mapper>
测试:新增博客
package com.zyh.mapping;
import com.zyh.pojo.Blog;
import com.zyh.utils.IDUtils;
import com.zyh.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;
import java.util.Date;
public class BlogMapperTest {
@Test
public void test(){
SqlSession session = MyBatisUtils.getSession(true);
BlogMapper mapper = session.getMapper(BlogMapper.class);
//新增博客
for (int i = 1; i <= 10; i++) {
Blog blog = new Blog();
blog.setId(IDUtils.getId());
blog.setTitle("Mybatis"+i);
blog.setAuthor("zyh");
blog.setCreateTime(new Date());
blog.setViews(399);
mapper.addBlog(blog);
}
session.close();
}
}
通过作者名字和博客名字来查询博客
如果作者的名字为空,就根据博客名字来查询
接口新增方法:
package com.zyh.mapping;
import com.zyh.pojo.Blog;
import java.util.List;
import java.util.Map;
public interface BlogMapper {
/**
* 插入数据
*/
int addBlog(Blog blog);
/**
* > 通过作者名字和博客名字来查询博客
* > 如果作者的名字为空,就根据博客名字来查询
* 如果不知道参数有几个,就使用Map进行传参
*/
List<Blog> getBlogByIf(Map map);
}
BlogMapper.xml
中的新增配置:
<select id="getBlogByIf" parameterType="map" resultType="Blog">
select * from mybatis.blog where
<if test="title!=null">
title=#{title}
if>
<if test="author!=null">
and author=#{author}
if>
select>
测试:
@Test
public void testgetBlogByIf(){
SqlSession session = MyBatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Map<String, String> map = new HashMap<String, String>();
map.put("title","Mybatis1");
map.put("author","zyh");
List<Blog> blogs = mapper.getBlogByIf(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
session.close();
}
执行结果:
案例2:where 如果测试时给这个方法传递的参数是一个空 map ,会发生什么呢?
测试:
@Test
public void testgetBlogByIf(){
SqlSession session = MyBatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Map<String, String> map = new HashMap<String, String>();
// map.put("title","Mybatis1");
// map.put("author","zyh");
List<Blog> blogs = mapper.getBlogByIf(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
session.close();
}
}
我们可以看到 Sql 语句报错,SQL: select * from mybatis.blog where
,如果参数为空,后面的where
语句的条件就为空,所以报错。
解决办法: 有 where
判断条件时可以使用动态SQL 标签,如果后面的条件为空,就可以自动去掉这个 where
,而且在where
标签中,如果where
后的条件是以or 或 and
开头,会自动去掉这个关键字。
在xml
中的sql语句:
select id="getBlogByIf" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<if test="title!=null">
title=#{title}
if>
<if test="author!=null">
and author=#{author}
if>
where>
select>
案例3:set 如果后面的条件满足,它就会自动拼接 set 标签,后面如果有多余的,就会自动去掉。
接口:
/**
* 更新博客数据
*/
int updateBlog(Map map);
xml
SQL配置
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="title!=null">
title=#{title},
if>
<if test="author!=null">
author=#{author}
if>
set>
where id=#{id}
update>
测试:
@Test
public void testUpdateBlog(){
SqlSession session = MyBatisUtils.getSession(true);
BlogMapper mapper = session.getMapper(BlogMapper.class);
Map<String,String> map = new HashMap<String, String>();
map.put("id","33889a4a983e43cbb6a4acf47cc64a86");
map.put("author","hang");
map.put("title","Spring");
mapper.updateBlog(map);
session.close();
}
如果我们只传递一个title
参数,那么title=#{title},
后面的逗号怎么办呢?set
就可以用来处理这个问题,会自动去掉这个逗号。
测试:
@Test
public void testUpdateBlog(){
SqlSession session = MyBatisUtils.getSession(true);
BlogMapper mapper = session.getMapper(BlogMapper.class);
Map<String,String> map = new HashMap<String, String>();
map.put("id","33889a4a983e43cbb6a4acf47cc64a86");
map.put("title","SpringMVC");
mapper.updateBlog(map);
session.close();
}
案例4: choose 类似于Java 中的Switch
接口:
/**
* 查询博客,只要满足一个条件即可
*/
List<Blog> queryBlogByChoose(Map map);
xml
中的SQL:
<select id="queryBlogByChoose" parameterType="map" resultType="Blog">
select * from mybatis.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>
测试:
第一次 :参数为空
@Test
public void testQueryBlogByChoose(){
SqlSession session = MyBatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Map<String,String> map = new HashMap<String, String>();
List<Blog> blogs = mapper.queryBlogByChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
session.close();
}
@Test
public void testQueryBlogByChoose(){
SqlSession session = MyBatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Map<String,String> map = new HashMap<String, String>();
map.put("author","hang");
List<Blog> blogs = mapper.queryBlogByChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
session.close();
}
@Test
public void testQueryBlogByChoose(){
SqlSession session = MyBatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Map<String,String> map = new HashMap<String, String>();
map.put("title","Mybatis3");
List<Blog> blogs = mapper.queryBlogByChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
session.close();
}
@Test
public void testQueryBlogByChoose(){
SqlSession session = MyBatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Map<String,String> map = new HashMap<String, String>();
map.put("title","SpringMVC");
map.put("author","hang");
List<Blog> blogs = mapper.queryBlogByChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
session.close();
}