动态SQL语句实现
if 查询
接口
public interface BlogMapper {
List<Blog> queryBlogIF(Map map);
}
Mapper.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="allen.dao.BlogMapper">
<!-- 根据不同查询条件查询-->
<!-- where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。-->
<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>
</mapper>
测试
public class MyTest {
@Test
public void queryBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map<String,String> map = new HashMap<>();
//根据 xml 文件查询 author 字段值为"保尔"的 Blog
map.put("author","保尔");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
}
trim(where,set)
where
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。
SET
用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。比如:
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
这个例子中,set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。
与 set 元素等价的自定义 trim 元素
<trim prefix="SET" suffixOverrides=",">
...
</trim>
注意,我们覆盖了后缀值设置,并且自定义了前缀值。
choose(和when配合使用)
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
接口
public interface BlogMapper {
List<Blog> queryBlogChoose(Map map);
}
Mapper.xml
<!-- choose-when 相当于java中的 switch-case-->
<select id="queryBlogChoose" parameterType="map" resultType="Blog">
select * from blog
<where>
<choose>
<when test="title != null">
and title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
views = #{views}
</otherwise>
</choose>
</where>
</select>
测试
@Test
public void queryBlogChoose(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map<String,String> map = new HashMap<>();
//当 title 不为 null 时,只返回 title 为 "java so easy"的 Blog,不再往下执行
map.put("title","java so easy");
map.put("views","510");
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
SQL片段
有的时候,我们可能想要将一些公共的部分抽取出来,方便复用!
1.使用SQL标签抽取公共部分
2.在需要使用的地方使用 include 标签引入即可
Mapper.xml
<!-- 提高代码复用-->
<sql id="if-title-author">
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</sql>
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from blog
<where>
<!-- 包含引用sql语句 -->
<include refid="if-title-author"></include>
</where>
</select>
注意事项:
1.最好基于单表定义SQL片段
2.不要在SQL片段中使用where标签
测试
@Test
public void queryBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map<String,String> map = new HashMap<>();
// map.put("title","java so easy");
map.put("author","保尔");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
输出
[allen.dao.BlogMapper.queryBlogIF]-==> Preparing: select * from blog WHERE author = ?
[allen.dao.BlogMapper.queryBlogIF]-==> Parameters: 保尔(String)
[allen.dao.BlogMapper.queryBlogIF]-<== Total: 2
Blog(id=b29f1be4a8d24ccabe26f316d834f052, title=钢铁是怎样炼成的, author=保尔, createTime=Sun Nov 22 22:50:07 CST 2020, views=510)
Blog(id=ba66644c43964e8fa62a0b229bf280df, title=py so easy, author=保尔, createTime=Mon Nov 23 22:06:39 CST 2020, views=20)
foreach
接口
public interface BlogMapper {
List<Blog> queryBlogForeach(Map map);
}
Mapper.xml
<!-- foreach查询-->
<!-- select * from blog where 1=1 and (id=1 or id=2 or id=3)-->
<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>
测试1 (ids为空)
@Test
public void queryBlogForeach(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
ArrayList<Integer> ids = new ArrayList<>();
map.put("ids",ids);
List<Blog> blogs = mapper.queryBlogForeach(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
输出1(注意观察 sql 语句)
[allen.dao.BlogMapper.queryBlogForeach]-==> Preparing: select * from blog
[allen.dao.BlogMapper.queryBlogForeach]-==> Parameters:
[allen.dao.BlogMapper.queryBlogForeach]-<== Total: 3
Blog(id=1, title=钢铁是怎样炼成的, author=保尔, createTime=Sun Nov 22 22:50:07 CST 2020, views=510)
Blog(id=2, title=java so easy, author=保尔1, createTime=Mon Nov 23 22:05:53 CST 2020, views=20)
Blog(id=3, title=py so easy, author=保尔, createTime=Mon Nov 23 22:06:39 CST 2020, views=20)
测试2(ids 传入参数1,2)
@Test
public void queryBlogForeach(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
ArrayList<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
map.put("ids",ids);
List<Blog> blogs = mapper.queryBlogForeach(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
输出2(注意观察 sql 语句)
[allen.dao.BlogMapper.queryBlogForeach]-==> Preparing: select * from blog WHERE ( id=? or id=? )
[allen.dao.BlogMapper.queryBlogForeach]-==> Parameters: 1(Integer), 2(Integer)
[allen.dao.BlogMapper.queryBlogForeach]-<== Total: 2
Blog(id=1, title=钢铁是怎样炼成的, author=保尔, createTime=Sun Nov 22 22:50:07 CST 2020, views=510)
Blog(id=2, title=java so easy, author=保尔1, createTime=Mon Nov 23 22:05:53 CST 2020, views=20)
==动态SQL就是在拼接SQL语句,只要保证SQL的正确性,按照SQL的格式排列即可==
建议:先在 Mysql 中写出对应的 SQL 语句,再对应修改为动态SQL语句即可。