目录
动态SQL
什么是动态SQL:动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句。
官方解释:
搭建环境
新建一个数据库表:blog
//字段:id,title,author,create_time,views
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 '浏览量'
);
1.创建Mybatis基础工程
2.IDutil工具类
import java.util.UUID;
//产生随机ID
public class IDUtil {
public static String getId(){
return UUID.randomUUID().toString().replaceAll("-","");
}
}
3.编写实体类
public class Blog {
private String id;
private String title;
private String author;
private Date creatTime;//属性名和字段名不一致 驼峰命名
private int views;
//get set 构造
}
4.编写Mapper接口及XML文件
//BlogMapper接口
public interface BlogMapper {
}
//BlogMapper.xml
<?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.damin.dao.BlogMapper">
</mapper>
5.mybatis核心配置文件
<settings>
<!-- 标准的日志工厂实现-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 是否开启自动驼峰命名规则映射-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<mappers>
<mapper class="com.damin.dao.BlogMapper"/>
</mappers>
6.插入初始数据
编写接口:
//插入数据
int addBlog(Blog blog);
BlogMapper配置文件:
<insert id="addBlog" parameterType="blog">
insert into blog (id, title, author, create_time, views)
values (#{id},#{title},#{author},#{creatTime},#{views});
</insert>
初始化博客方法:
@Test
public void addInitBlog(){
SqlSession session = MybatisUtils.getSqlSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = new Blog();
blog.setId(IDUtil.getId());
blog.setTitle("Mybatis如此简单");
blog.setAuthor("无敌敏");
blog.setCreatTime(new Date());
blog.setViews(9999);
mapper.addBlog(blog);
blog.setId(IDUtil.getId());
blog.setTitle("Java如此简单");
mapper.addBlog(blog);
blog.setId(IDUtil.getId());
blog.setTitle("Spring如此简单");
mapper.addBlog(blog);
blog.setId(IDUtil.getId());
blog.setTitle("微服务如此简单");
mapper.addBlog(blog);
session.close();
}
至此,搭建环境及初始化数据完成!
if 、where
需求:根据作者名字和博客名字查询博客!如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名字来查询。
1.编写接口类:
//查询博客
List<Blog> queryBlogIF(Map map);
2.编写SQL语句:
<!-- select * from blog where title = #{title} and author = #{author} -->
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title != null">
and title = #{title}
</if>
<if test="author!=null">
and author=#{author}
</if>
</where>
</select>
3.测试:
@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","无敌敏");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
这个"where"标签会知道如果它包含的标签中有返回值的话,它就插入一个"where"。此外,如果标签返回的内容是以 and 或 or 开头的,则它会自动去除。
set
同理,上面的对于查询SQL语句包含where标签,在进行更新操作时,使用set标签。
//编写BlogMapper接口
//更新博客
int UpDateBlog(Map map);
//编写BlogMapper.xml
<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>
//测试
@Test
public void UpDateBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
map.put("title","Mybatis如此简单2");
//注意这里的id是随机生成的,而不是平时写的1 2 3...
map.put("id","1f6825639436460cb83617df57b7bafd");
mapper.UpDateBlog(map);
sqlSession.close();
}
choose
有的时候,我们不想用到所有的查询条件,指向选择其中的一个,查询条件有一个满足即可,使用choose变迁可以解决此类问题,类似于Java中地switch语句。
//编写BlogMapper接口
List<Blog> queryBlogChoose(Map map);
//编写BlogMapper.xml
<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>
//测试
@Test
public void queryBlogChoose(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
map.put("title","Mybatis如此简单");
map.put("author","无敌敏");
map.put("views",9999);
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
SQL片段
有的时候可能某个sql语句我们使用地特别多,为了增加代码地重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
提取SQL片段:
<sql id="if-title-author">
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
引用SQL片段:
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
<include refid="if-title-author"></include>
<!-- 在这里还可以引用其他的 sql 片段 -->
</where>
</select>
Foreach
也就是对集合进行遍历
需求:我们需要查询blog表中id分别为1,2,3的博客信息(注意:在添加博客信息时,使用了工具类IDUtil,所以id并不是1 2 3,而是随机的,我在这里是先查询了其中三个博客的id拿来用的,为了方便也可以把ID改回1 2 3)
//编写BlogMapper接口
List<Blog> queryBlogForeach(Map map);
//编写BlogMapper.xml
<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 queryBlogForeach(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
ArrayList<String> ids = new ArrayList<String>();
ids.add("1f42bd60580149f0ab8149e150341e46");
map.put("ids",ids);
List<Blog> blogs = mapper.queryBlogForeach(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
注意:下面这条语句中open="and (",and 和 ( 之间是有一个空格的,不要忘记写,不然会报错。
总结
其实 sql 语句的编写往往就是一个拼接的问题,为了保证拼接准确,我们最好先把原生的sql语句写出来,然后再通过 mybatis 动态SQL对照着改,防止出错。
日常感谢“狂神”老师!
注解动态SQL
mybatis的注解也支持动态SQL。mybatis提供了各种注解,如@InsertProvider、@UpdateProvider、@DeleteProvider和@SelectProvider,来帮助构建动态SQL语句。
以上四个Provider注解都有type属性,该属性指定了一个类。method属性,指定该类的方法,其用来提供需要执行的SQL语句。传统的使用字符串拼接的方法构建SQL语句是非常困难的,并且容易出错。所有mybatis提供了一个SQL工具类org.apache.ibatis.jdbc.SQL,该类不适用字符串拼接的方式,并且会以合适的空格前缀和后缀来构造SQL语句。
//动态查询
@SelectProvider(type = DeptDynaSqlProvider.class,method = "selectWhitParam")
List<Dept> selectByPage(Map<String,Object> params);
//分页动态查询
public String selectWhitParam(final Map<String,Object> params){
String sql = new SQL(){
{
SELECT("*");
FROM(DEPTTABLE);
if (params.get("dept") != null) {
Dept dept = (Dept) params.get("dept");
if (dept.getName() != null && !dept.getName().equals("")) {
WHERE(" name LIKE CONCAT ('%', #{dept.name},'%') ");
}
}
}
}.toString();
if (params.get("pageModel") != null){
sql += " limit #{pageModel.firstLimitParam} , #{pageModel.pageSize} ";
}
return sql;
}