一、学习目标
在之前的学习中,使用的都是静态sql,而动态SQL相比静态SQL具有多个显著的优点。
首先。,动态SQL允许根据程序运行时的条件和需求来动态地生成SQL语句。这意味着它可以根据不同的情境和需求生成不同的SQL语句,从而提供更高的灵活性和适应性。
此外,动态SQL支持参数化查询,这意味着可以重用相同的SQL语句模板,仅通过改变参数值来适应不同的查询需求。动态SQL还可以根据不同的条件和逻辑判断,在查询语句中动态添加或移除特定的查询逻辑,这使得查询过程更加灵活。
二.搭建环境
1.数据库
在数据库里新建一张表
CREATE TABLE `blog` (
`id` varchar(50) NOT NULL ,
`classified_column` varchar(40) NOT NULL ,
`title` varchar(100) NOT NULL ,
`author` varchar(30) NOT NULL ,
`create_time` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
2.创建工程
项目结果如下:
其中,db.properties和log4j.properties文件可参考之前的博客。
实体类
@Data
public class Blog {
private String id;
private String classifiedColumn;
private String title;
private String author;
private Date createTime;
}
工具类
public class IDUtil {
public static String genId(){
return UUID.randomUUID().toString().replaceAll("-","");
}
}
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "MybatisConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession连接
public static SqlSession getSession(){
return sqlSessionFactory.openSession();
}
}
mybatisConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties"/>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="LOG4J"/>
</settings>
<typeAliases>
<package name="com.lzh.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- JDBC 驱动-->
<property name="driver" value="${mysql.driver}"/>
<!-- url数据库的 JDBC URL地址。-->
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="Mapper/BlogMapper.xml"/>
</mappers>
</configuration>
添加数据:
接口类添加:
int addBlog(Blog blog);
xml文件里添加
<insert id="addBlog" parameterType="blog">
insert into blog (id, classified_column, title, author, create_time)
values (#{id},#{classifiedColumn},#{title},#{author},#{createTime});
</insert>
测试·
@Test
public void testAddBlog(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = new Blog();
blog.setId(IDUtil.genId());
blog.setClassifiedColumn("mybatis");
blog.setTitle("lzh学习Mybatis的第一天");
blog.setAuthor("lzh");
blog.setCreateTime(new Date());
mapper.addBlog(blog);
blog.setId(IDUtil.genId());
blog.setTitle("lzh学习Mybatis的第二天");
blog.setCreateTime(new Date());
mapper.addBlog(blog);
blog.setId(IDUtil.genId());
blog.setTitle("lzh学习Mybatis的第三天");
blog.setCreateTime(new Date());
mapper.addBlog(blog);
session.commit();
session.close();
}
三、动态sql
介绍
动态 SQL 是 MyBatis 的强大特性之一,它允许你在 XML 映射文件中编写灵活的 SQL 语句。在使用过 JDBC 或其它类似的框架时,需要根据不同条件拼接 SQL 语句,而且拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。这无疑是不方便的,利用动态 SQL,可以摆脱这种不便。
MyBatis 提供了几种动态 SQL 元素来支持灵活的 SQL 语句编写:
1.if
它允许在 SQL 语句中加入一个条件判断,如果条件为真,则包含该片段。
1.在接口类中添加以下方法:
List<Blog> queryIf(Map map);
2.在xml文件添加:
<select id="queryIf" parameterType="map" resultType="blog">
select * from blog where
<if test="title != null">
title = #{title}
</if>
<if test="classifiedColumn != null">
and classifiedColumn=#{classifiedColumn}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
3.测试:
@Test
public void testQueryIf(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
// 创建一个HashMap来存储查询条件,这里使用String作为键和值的类型
HashMap<String, String> map = new HashMap<String, String>();
// 设置查询条件
map.put("title","lzh学习Mybatis的第一天");
//map.put("author","lzh");
// 调用BlogMapper接口中的queryIf方法,传入查询条件map,执行查询并返回结果
List<Blog> blogs = mapper.queryIf(map);
// 打印查询结果
System.out.println(blogs);
session.close();
}
2.where
用于动态生成 WHERE 条件语句,MyBatis 会智能地处理 WHERE 关键字和前导的 AND 或 OR
以上面的测试为例,如果将语句 map.put("author","lzh");的注释去掉,注释掉map.put("author","lzh"); 然后再测试,你会发现居然报错了
原因就在于下面的前导的 and
这个时候,where语句的作用就凸显出来了
1.修改xml文件,添加where语句:
<select id="queryIf" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="classifiedColumn != null">
and classifiedColumn=#{classifiedColumn}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
2.测试
@Test
public void testQueryIf(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
// 创建一个HashMap来存储查询条件,这里使用String作为键和值的类型
HashMap<String, String> map = new HashMap<String, String>();
// 设置查询条件
//map.put("title","lzh学习Mybatis的第一天");
map.put("author","lzh");
// 调用BlogMapper接口中的queryIf方法,传入查询条件map,执行查询并返回结果
List<Blog> blogs = mapper.queryIf(map);
// 打印查询结果
System.out.println(blogs);
session.close();
}
3.choose
类似于 Java 或其他编程语言中的 switch 或 if-else 语句,它包含了一个或多个条件判断。
1.在接口类添加:
List<Blog> queryChoose(Map map);
2.在xml文件里添加:
<select id="queryChoose" 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 classfiedColumn = #{classfiedColumn}
</otherwise>
</choose>
</where>
</select>
3.测试:
@Test
public void testQueryChoose(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
// 创建一个HashMap来存储查询条件,这里使用Object作为值的类型以支持多种数据类型
HashMap<String, Object> map = new HashMap<String, Object>();
// 设置查询条件,这里假设我们要根据title、classifiedColumn和author来查询Blog
map.put("title","lzh学习Mybatis的第一天");
map.put("classifiedColumn","mybatis");
map.put("author","lzh");
// 调用BlogMapper接口中的queryChoose方法,传入查询条件map,执行查询并返回结果
List<Blog> blogs = mapper.queryChoose(map);
// 打印查询结果
System.out.println(blogs);
session.close();
}
4.set
用于动态生成 SET 语句,用于更新操作,MyBatis 会智能地处理 SET 关键字和逗号。
1.在接口类添加:
int update(Map map);
2.在xml文件添加:
<update id="update">
update blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="classifiedColumn != null">
classifiedColumn = #{classifiedColumn},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id=#{id};
</update>
3.测试:
@Test
public void testUpdate(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
// 创建一个HashMap来存储更新操作的字段和值
HashMap<String, String> map = new HashMap<String, String>();
// 设置需要更新的字段和对应的值
map.put("title","mybatis学习第四天"); // 更新title字段为"mybatis学习第四天"
map.put("author","lzh"); // 更新author字段为"lzh"
map.put("id","dee718d55eec4d34bdcc14c1650639ca"); // 指定要更新的记录的ID
// 调用BlogMapper接口中的update方法,传入包含更新字段和值的HashMap,执行更新操作
mapper.update(map);
// 提交事务,确保更新操作被保存到数据库
session.commit();
session.close();
}
5.foreach
用于处理一个集合,通常用于 IN 条件语句。
1.在接口类添加:
List<Blog> queryForeach(Map map);
2.在xml文件添加:
<select id="queryForeach" parameterType="map" resultType="blog">
select * from blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id=#{id}
</foreach>
</where>
</select>
3.测试:
@Test
public void testQueryForeach(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
// 创建一个HashMap来存储查询条件,这里用作动态SQL的输入参数
HashMap map = new HashMap();
// 创建一个ArrayList来存储需要查询的Blog ID列表
List<Integer> ids = new ArrayList<Integer>();
// 向ID列表中添加需要查询的Blog ID
ids.add(1);
ids.add(2);
ids.add(3);
// 将ID列表作为查询条件放入HashMap中,键为"ids"
map.put("ids",ids);
// 调用BlogMapper接口中的queryForeach方法,传入查询条件map,执行查询并返回结果
List<Blog> blogs = mapper.queryForeach(map);
// 打印查询结果
System.out.println(blogs);
session.close();
}