Mybatis入门之mapper映射(案例Demo包括分页实现)

动态sql相关

mybatis支持强大的动态生成sql功能,提供了一些标签实现动态sql拼接, 更加灵活。

mapper.xml的常用标签(参考:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html):

标签 描述

<mapper>

映射文件的根节点,包含所有关于映射的配置

<resultMap>

定义返回集合的属性形式,适合用于返回自定义属性组合时的情况

<constructor>

<resultMap>的子节点,用于以构造函数的形式生成返回属性

<idArg>

<constructor>的子标签,表示实体主键
<sql> 可以重用的 SQL 块,也可以被其他语句引用,与<include>标签结合使用,id必须唯一
<include> 表示引用一个<sql>语句体,refid属性指定<sql>标签的id
<insert>、<select>、<update>、<delete> 分别对应C(create)R(read)U(update)D(delete)

1.if标签的使用,此种方式需要使用注解传参(不使用注解的话test表达式里面参数应该用value表示)

   //1.动态sql之if
   Book queryOneByBookId(@Param("bookId")Integer bookId);
   <if test="null!=bookId and ''!=bookId">
      and id = #{bookId}
    </if>

2.trim标签的使用,包含去除前后缀的操作,可以与if结合使用

<insert id="insertSelective" parameterType="com.star.model.Book" >
    insert into t_book_vue
    <!--
    prefix:代表前缀(
    suffix:代表后缀)
    suffixOverrides:去除末尾的后缀,
    prefixOverrides:去除开头的前缀
     -->
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null" >
        id,
      </if>
      <if test="bookname != null" >
        bookname,
      </if>
      <if test="price != null" >
        price,
      </if>
      <if test="booktype != null" >
        booktype,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=INTEGER},
      </if>
      <if test="bookname != null" >
        #{bookname,jdbcType=VARCHAR},
      </if>
      <if test="price != null" >
        #{price,jdbcType=REAL},
      </if>
      <if test="booktype != null" >
        #{booktype,jdbcType=VARCHAR},
      </if>
    </trim>
</insert>

3.foreach标签的使用,可以循环遍历标签体的内容

  <!-- foreach用法 -->
  <select id="queryBookByForeach" resultType="com.star.model.Book">
    <include refid="base_query_list"/>
    and id in
    <!--
      conllection:代表要循环的参数
      item: 每一项的别名自定义
      open:开头前缀
      close: 结尾后缀
      separator:每项之间插入字符
    -->
    <foreach collection="list" item="id" open="(" close=")" separator=",">
      #{id}
    </foreach>
    <include refid="base_order"/>
  </select>

4.choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似

  <!--
    id:唯一
    parameterType:参数类型
    resultType:返回类型
   -->
  <select id="dynamicChooseTest" parameterType="com.star.model.Book" resultMap="BaseResultMap">
    <include refid="base_query_list"/>
    <!-- 满足表达式拼接标签体sql语句 -->
    <choose>
      <when test="bookname != null">
        and bookname like concat('%',#{bookname},'%')
      </when>
      <when test="booktype != null">
        and booktype = #{booktype}
      </when>
      <otherwise>
        and 2 = 2
      </otherwise>
    </choose>
    <include refid="base_order"/>
  </select>

5.where (主要是用来简化sql语句中where条件判断的,能智能的处理 and or 条件)

  <!--
    id唯一
    where标签跟在表名的后面,与if标签结合使用
  -->
  <select id="dynamicWhereTest" parameterType="com.star.model.Book" resultMap="BaseResultMap">
    select * from t_book_vue
    <where>
      <if test="bookname != null">
        bookname = #{bookname}
      </if>
      <if test="booktype != null">
        and booktype = #{booktype}
      </if>
    </where>
  </select>

6.set主要是用在更新操作的时候,它的主要功能和where元素其实是差不多的,主要是在包含的语句前输出一个set,然后如果包含的语句是以逗号结束的话将会把该逗号忽略,如果set包含的内容为空的话则会出错。有了set元素我们就可以动态的更新那些修改了的字段

  <!--
    set标签与where标签大同小异
  -->
  <update id="dynamicSetTest" parameterType="com.star.model.Book">
    update t_book_vue
    <set>
      <if test="bookname != null">
        bookname = #{bookname},
      </if>
      <if test="booktype != null">
        booktype = #{booktype},
      </if>
    </set>
    where id = #{id}
  </update>

分页查询实现

mybatis其实本身自带分页的实现,但是分页功能很弱(基于内存,查出所有记录在按偏移量offset和边界limit取结果),大数据情况下不适合使用,所以我们借助其他的分页工具实现。

1.导入分页插件,这个插件使用拦截器实现分页

       <dependency>
         <groupId>com.github.pagehelper</groupId>
         <artifactId>pagehelper</artifactId>
         <version>5.1.2</version>
       </dependency>

2.将pagehelper插件配置到mybatis.cfg.xml中:

       <!--要注意plugins的位置,要在别名配置之后 
      配置分页插件PageHelper, 4.0.0以后的版本支持自动识别使用的数据库 -->
       <plugin interceptor="com.github.pagehelper.PageInterceptor">
       </plugin>

3.准备一个包含常用操作的pageBean对象:

package com.star.util;

import java.io.Serializable;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

public class PageBean implements Serializable {

    private static final long serialVersionUID = 2422581023658455731L;

    //页码
    private int page=1;
    //每页显示记录数
    private int rows=10;
    //总记录数
    private int total=0;
    //是否分页
    private boolean isPagination=true;
    //上一次的请求路径
    private String url;
    //获取所有的请求参数
    private Map<String,String[]> map;
    
    public PageBean() {
        super();
    }
    
    //设置请求参数
    public void setRequest(HttpServletRequest req) {
        String page=req.getParameter("page");
        String rows=req.getParameter("rows");
        String pagination=req.getParameter("pagination");
        this.setPage(page);
        this.setRows(rows);
        this.setPagination(pagination);
        this.url=req.getContextPath()+req.getServletPath();
        this.map=req.getParameterMap();
    }
    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public Map<String, String[]> getMap() {
        return map;
    }

    public void setMap(Map<String, String[]> map) {
        this.map = map;
    }

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }
    
    public void setPage(String page) {
        if(null!=page&&!"".equals(page.trim()))
            this.page = Integer.parseInt(page);
    }

    public int getRows() {
        return rows;
    }

    public void setRows(int rows) {
        this.rows = rows;
    }
    
    public void setRows(String rows) {
        if(null!=rows&&!"".equals(rows.trim()))
            this.rows = Integer.parseInt(rows);
    }

    public int getTotal() {
        return total;
    }

    public void setTotal(int total) {
        this.total = total;
    }
    
    public void setTotal(String total) {
        this.total = Integer.parseInt(total);
    }

    public boolean isPagination() {
        return isPagination;
    }
    
    public void setPagination(boolean isPagination) {
        this.isPagination = isPagination;
    }
    
    public void setPagination(String isPagination) {
        if(null!=isPagination&&!"".equals(isPagination.trim()))
            this.isPagination = Boolean.parseBoolean(isPagination);
    }
    
    /**
     * 获取分页起始标记位置
     * @return
     */
    public int getStartIndex() {
        //(当前页码-1)*显示记录数
        return (this.getPage()-1)*this.rows;
    }
    
    /**
     * 末页
     * @return
     */
    public int getMaxPage() {
        int totalpage=this.total/this.rows;
        if(this.total%this.rows!=0)
            totalpage++;
        return totalpage;
    }
    
    /**
     * 下一页
     * @return
     */
    public int getNextPage() {
        int nextPage=this.page+1;
        if(this.page>=this.getMaxPage())
            nextPage=this.getMaxPage();
        return nextPage;
    }
    
    /**
     * 上一页
     * @return
     */
    public int getPreivousPage() {
        int previousPage=this.page-1;
        if(previousPage<1)
            previousPage=1;
        return previousPage;
    }

    @Override
    public String toString() {
        return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", isPagination=" + isPagination
                + "]";
    }
}

4.后面会给源码,这里给具体的实现:

        //分页实现
        PageBean pageBean = new PageBean();
        pageBean.setPage(2);
        pageBean.setRows(5);
        
        //给分页插件填充页码和行数
        if(null!=pageBean&&pageBean.isPagination())
           PageHelper.startPage(pageBean.getPage(),pageBean.getRows());

        //查询实现
        List<Book> books = bookService.queryBookPager(new Book(), pageBean);
        System.out.println(books.getClass());
        //判断分页
        if(null!=pageBean&&pageBean.isPagination()&&null!=books){
            PageInfo<Book> pageInfo = new PageInfo<>(books);
            System.out.println("总记录数:"+pageInfo.getTotal());
            System.out.println("当前页码:"+pageInfo.getPageNum());
            System.out.println("显示条数:"+pageInfo.getPageSize());
            List<Book> list = pageInfo.getList();
            list.forEach(System.out::println);
        }
    

5.junit单元测试成功如下:

完整源码地址

https://www.cnblogs.com/StarChen20/p/13944051.html

原文地址:https://www.cnblogs.com/StarChen20/p/13938179.html