Mybatis 动态SQL

Mybatis 动态SQL

动态SQL就是根据不同的条件生成不同的SQL语句

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

建立实体类:

 代码:

package com.xiaofu.pojo;
import java.util.Date;

public class Blog {
    private int id;
    private String title;
    private String author;
    private Date createTime;
    private int views;

    public Blog() {
    }
    public Blog(int id, String title, String author, Date createTime, int views) {
        this.id = id;
        this.title = title;
        this.author = author;
        this.createTime = createTime;
        this.views = views;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public int getViews() {
        return views;
    }

    public void setViews(int views) {
        this.views = views;
    }

    @Override
    public String toString() {
        return "Blog{" +
                "id=" + id +
                ", title=" + title +
                ", author='" + author + '\'' +
                ", createTime=" + createTime +
                ", views=" + views +
                '}';
    }
}

建立接口和对应xml

 在核心配置文件中注册 创建的BlogMapper.xml

2.if语句:

 编写一个接口:

package com.xiaofu.dao;
import com.xiaofu.pojo.Blog;
import java.util.List;
import java.util.Map;

public interface BlogMapper {

    //查询博客
    List<Blog> queryBlogIf(Map map);

}

 用 if 实现接口:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaofu.dao.BlogMapper">
        <select id="queryBlogIf" parameterType="map" resultType="com.xiaofu.pojo.Blog">
            select * from blog where 1=1

            <if test="title != null">
                and title = #{title}
            </if>
            <if test="author != null">
                and author = #{author}
            </if>

        </select>
<!--     <if test="title != null"> 如果title不等于空 就在sql后面加上 and title = #{title} -->
</mapper>

编写测试类:

 @Test
    public void getlist(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("title","数据库"); //查询title为数据库的所有信息
//        map.put("author","老王") //查询author为老王的所有信息;
        List<Blog> blogs = mapper.queryBlogIf(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

现在数据库有这些数据:

 运行测试类:

 查询出来了 title 等于 数据库的 数据

3.其他动态SQL常用标签:

choose、when、otherwise

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

还是上面的例子,但是策略变为:传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG(这可能是管理员认为,与其返回大量的无意义随机 Blog,还不如返回一些由管理员精选的 Blog)。

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

trim、where、set

 set

set标签 - 解决更新数据表时字符串拼接逗号”,”问题;

没有使用 if 标签时,如果有一个参数为 null,都会导致错误。

当在 update 语句中使用 if 标签时,如果最后的 if 没有执行,则或导致逗号多余错误。

使用 set 标签可以将动态的配置 set 关键字,和剔除追加到条件末尾的任何不相关的逗号。

#如果最后的if没有执行,会导致逗号多余错误。

<update id="updateUser">
  update User SET
      <if test="name != null">
          name =#{name},
      </if>
      <if test="age != null">
          age=#{age},
      </if>
      <if test="phone != null">
          phone =#{phone},
      </if>
      <if test="class != null">
          class=#{class}
      </if>
  where id=#{id}
</update>
<!--    set标签除掉条件末尾的逗号-->
    <update id="updateUser">
        update User
        <set>
            <if test="name != null">
                name=#{name},
            </if>
            <if test="age != null">
                age=#{age},
            </if>
            <if test="phone != null">
                phone=#{phone},
            </if>
            <if test="class != null">
                adress=#{adress}
            </if>
            where class=#{class}
        </set>
    </update>

where标签 - 解决if标签拼接字符串AND符号问题

where 标签只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,

where 元素也会将它们去除。这样我们就不用在where后面加一个1=1了

当 if 标签较多时,这样的组合可能会导致错误。 如下:

<select id="getRoleListWhere" parameterType="Role" resultMap="roleResultMap">
    SELECT * FROM role WHERE
    <if test="name!=null and name!=' ' ">
        name = #{name}
    </if>
    <if test="roletype!=null and roletype!=' ' ">
        AND roletype = #{roletype}
    </if>
    <if test="userid!=null">
        AND userid = #{userid}
    </if>
</select>

当 name 值为 null 时,查询语句会出现 “WHERE AND” 的情况,解决该情况除了将"WHERE"改为“WHERE 1=1”之外,还可以利用 where标签。

这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以 AND 或 OR 开头的,则它会剔除掉。

<select id="selectRoleListByRole" parameterType="Role" resultMap="roleResultMap">
    <include refid="myselect"></include>
    <where>
        <if test="name!=null and name!=''">
            name = #{name}
        </if>
        <if test="roletype!=null and roletype!=''">
            AND roletype = #{roletype}
        </if>
        <if test="userid!=null">
            AND userid = #{userid}
        </if>
    </where>
</select>

trim

set 和 where 其实都是 trim 标签的一种类型, 该两种功能都可以使用 trim 标签进行实现。如果你不满足于where和set实现的功能你就可以使用trim来自定义实现。其中trim有四个主要的属性,分别是:

  • prefix:在sql语句加上前缀
  • suffix:在sql语句加上后缀
  • prefixOverrides:去除指定的前缀内容,比如:prefixOverrides=“AND | OR”,去除sql语句多余的前缀"AND"或者"OR"。
  • suffixOverrides:去除指定的后缀内容,比如:suffixOverrides=",",去除sql语句多余的逗号。

自定义实现3.1的set,去除update语句后缀多余的逗号

<update id="updateUser" resultType="User">
    update user set 
    <trim  suffixOverrides=",">
        <if test="class != null">
             class = #{class},
        </if>
        <if test="phone != null and adress != null">
            age > #{age},
        </if>
    </trim> 
    where class=#{class}
</update>

自定义实现3.2的where,去除where子句前缀多余的AND

<select id="findUser" resultType="User">
    select * from user
    <trim prefix="WHERE" prefixOverrides="AND | OR">
        <if test="class != null">
            AND class = #{class}
        </if>
        <if test="phone != null and adress != null">
            AND age > #{age}
        </if>
    </trim>
</select>

sql标签 - 可以提取重复sql语句片段

当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。为求 <select> 结构清晰也可将 sql 语句分解。

<sql id="myselect">
    SELECT * FROM role
</sql>

include - 用于引用定义的常量

<resultMap type="Role" id="roleRM">
    <id property="id" column="idrole" />
</resultMap>
<select id="selectAllRole" resultMap="roleRM">
    <include refid="myselect"></include>
</select>

<select id="selectRoleListByids" resultMap="roleRM">
    <include refid="myselect"></include></select>
<--  <include refid="myselect"></include>  引用上面写好的sql片段-->

foreach

主要用于构建 in 条件,可在 sql 中对集合进行迭代。也常用到批量删除、添加等操作中。

 - collection:collection 属性的值有三个分别是 list、array、map 三种,分别对应的参数类型为:List、数组、map 集合。

 - item:表示在迭代过程中每一个元素的别名

 - index:表示在迭代过程中每次迭代到的位置(下标)

 - open:前缀

 - close:后缀

 - separator:分隔符,表示迭代时每个元素之间以什么分隔

<select id="findUser" resultType="User">
  SELECT * FROM user
    where class in
    <foreach item="item" index="index" collection="classList" open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

 

posted @ 2021-01-04 11:52  lovelife80  阅读(110)  评论(0编辑  收藏  举报