Mybatis动态SQL与分页

动态 SQL

通常写在mapper包下面的地址映射配置文件(.xml)中。根据条件的不同, SQL 语句也会随之动态的改变. MyBatis 中,提供了一组标签用于实现动态 SQL
动态SQL语句标签包括以下标签:

1、If标签

条件判断标签,通过判断参数取值来决定是否使用某个查询条件,基本用法如下:

   

 <select id="queryBookIf" resultType="mybatis01.model.Book">
      select <include refid="Base_Column_List"/>
      from t_book where 1=1
      <if test="null!=bookType and ''!=bookType">
        <!--book_type 为数据库字段名-->
         <!--bookType为实体类属性名-->
        and book_type=#{bookType}
     
      </if>
      </select>

这里上面的sql语句后面必须添加 where 1=1 或者 使用where标签

if在这里是判断,判断书本类型是否为空 不为空就根据书本类型查询

id为mMapper的接口方法名,resultType为结果集类型

test 属性用于指定判断条件.

<include refid="Base_Column_List"/>为查询的所有字段

<sql id="Base_Column_List" >
  book_id, book_name, book_name_pinyin, book_price, book_type
</sql>

2、trim标签:

trim标签用于控制sql语句的前缀及后缀,其具体属性如下:
属性    描述
prefix    指定sql语句拼接的前缀
subfix    指定sql语句拼接的后缀
prefixOverrides    指定sql语句前面要去除的关键字或字符,如and 逗号 括号等
suffixOverrides    指定sql语句后面要去除的关键字或字符

   

 <insert id="insertSelective" parameterType="mybatis01.model.Book" >
        insert into t_book
        
        <!--prefix 在sql语句前拼一个(
            insert into t_book (
        -->
        <!--suffix在sql语句后拼一个(
             insert into t_book ()
        -->
        <!-- suffixOverrides 去除最后一个逗号
                insert into t_book (book_id,book_name,)
                取消这sql语句中最后一个逗号
         -->
        
        <trim prefix="(" suffix=")" suffixOverrides="," >
          <if test="bookId != null" >
            book_id,
          </if>
          <if test="bookName != null" >
            book_name,
          </if>
          <if test="bookNamePinyin != null" >
            book_name_pinyin,
          </if>
          <if test="bookPrice != null" >
            book_price,
          </if>
          <if test="bookType != null" >
            book_type,
          </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides="," >
          <if test="bookId != null" >
            #{bookId,jdbcType=INTEGER},
          </if>
          <if test="bookName != null" >
            #{bookName,jdbcType=VARCHAR},
          </if>
          <if test="bookNamePinyin != null" >
            #{bookNamePinyin,jdbcType=VARCHAR},
          </if>
          <if test="bookPrice != null" >
            #{bookPrice,jdbcType=REAL},
          </if>
          <if test="bookType != null" >
            #{bookType,jdbcType=VARCHAR},
          </if>
        </trim>
      </insert>

动态的新增方法,判断实体类的属性是否为空,为空则不给予添加此对应的字段

3、foreach标签

动态sql的一个常用操作时要求对一个集合进行遍历,比如说使用in操作符就会用到
属性    描述
collection    表示迭代集合的名称,一般可为list、set、array、map,该参数为必选参数
item    本次迭代获取的元素,如collection为list、set、array则item为其中元素,若为map,则item为key-value中的alue,必填参数
open    表示该语句以什么开始,最常见的是左括号“(” , 可选参数
close    表示该语句以什么结束,最常见的是右括号“)” , 可选参数
separator    分隔符,mybatis会在每次迭代后给item后添加一个分隔符,一般为逗号,可选参数
index    在list set 数组中,index表示当前迭代元素的下标,在map中index表示key-value中的key,可选参数

   

 <select id="queryBookByForeach" resultType="mybatis01.model.Book">
        select <include refid="Base_Column_List"/> from t_book where 1=1 and book_id in(
        <!--循环遍历此ids集合
            迭代获取的元素名称id自己定义
        -->
        
        <foreach collection="ids" item="id" separator=",">
          #{id}
        </foreach>
        )
      </select>
     
    <!--
        selelct book_id, book_name, book_name_pinyin, book_price, book_type from t_book
        where 1=1 and book_id in( 3 ,5 ,6)
        最后一个逗号foreach会自动删除
    -->

4、choose标签

       有时候,我们并不想应用所有的条件,而只是想从多个选项中选一个,而if标签是只要条件为真就会执行sql拼装.这时就需要使用choose标签,choose与java的switch功能类似;

mybatis会依次顺序判断各choose中的条件,当when某个条件满足时,就会跳出choose,即只选择第一个满足条件的when,如果choose中的条件都不满足,则执行otherwise中的语句;

总结:choose otherwise 类似于java的 switch…in case…default

  

  <select id="queryBookChoose" resultType="mybatis01.model.Book">
        select <include refid="Base_Column_List"/> from t_book where 1=1
      <choose>
        <when test="bookName!=null and ''!=bookName">
          and  book_name like concat('%',#{bookName},'%')
        </when>
        <when test="bookName!=null and ''!=bookName">
          and  book_type like concat('%',#{bookType},'%')
        </when>
        <otherwise>
          and  bookId =#{bookId}
        </otherwise>
      </choose>
    </select>

在此,判断书本名称是否为空,不为空就根据书本名称模糊查询,书本类型是否为空,不为空就根据书本类型模糊查询,假如都为空就根据书本id查询

5、set

set用于更新的sql语句中

在update时,多条件更新,每个属性后面要加逗号“,”,这个时候可能会出现多一个“,”的情况,此时我们就可以使用set去掉后边的“,”,除此之外我们使用前面说的trim也可实现当前的操作

    <update id="updateByPrimaryKeySelective" parameterType="mybatis01.model.Book" >
        update t_book
        <set >
          <if test="bookName != null" >
            book_name = #{bookName,jdbcType=VARCHAR},
          </if>
          <if test="bookNamePinyin != null" >
            book_name_pinyin = #{bookNamePinyin,jdbcType=VARCHAR},
          </if>
          <if test="bookPrice != null" >
            book_price = #{bookPrice,jdbcType=REAL},
          </if>
          <if test="bookType != null" >
            book_type = #{bookType,jdbcType=VARCHAR},
          </if>
        </set>
        where book_id = #{bookId,jdbcType=INTEGER}
      </update>

修改方法,假如实体类属性为空就不修改此属性所对于的字段

6、where

用于管理 where 子句. 有如下功能:
1) 如果没有条件, 不会生成 where 关键字
2) 如果有条件, 会自动添加 where 关键字
3) 如果第一个条件中有 and, 自动去除之

 

   <select id="queryBookWhere" resultType="mybatis01.model.Book">
        select <include refid="Base_Column_List"/> from t_book
        <where>
          <if test="bookType!=null and bookType!=''">
            and book_Type=#{bookType}
          </if>
          <if test="bookName!=null and bookName!=''">
            and book_name=#{bookName}
          </if>
        </where>
      </select>

mybatis传参

1、八大基础类型

    Mapper接口
    //传递Integer类型的参数,等同于传递八大基础类型
    List<Book> queryBookId(Integer bookId);

     实现对应Mapper接口的xml    

    <select id="queryBookId" resultType="mybatis01.model.Book">

    select <include refid="Base_Column_List"/> from t_book where 1=1

    <if test="null!=value and ''!=value">

             and book_id=#{undefinedvalue}

    </if>

    </select>

    这里的if标签的test条件使用的value 不能写参数名称       

     但是if标签里面取值可以直接写参数名取值

2、String类型参数

    Mapper接口
    必须使用@Param方式,并且指明参数名
 

   List<Book> queryBookType(@Param("bType") String bookType);

     实现对应Mapper接口的xml    

  <select id="queryBookType" resultType="mybatis01.model.Book">
      select <include refid="Base_Column_List"/> from t_book where 1=1
      <if test="null!=bType and ''!=bType">
        and book_type=#{bType}
      </if>
    </select>

    这里使用的是注解里面设置的参数名称,不能写参数里面的参数名称,也不能写value

3、传递对象或者集合

    Mapper接口
    List<Book> queryBookObject(Book book);

    实现对应Mapper接口的xml   

//对象

    <select id="queryBookObject" resultType="mybatis01.model.Book">

    select <include refid="Base_Column_List"/> from t_book where 1=1

            <if test="null!=bookType and ''!=bookType">

                    and book_type=#{bookType}

            </if>

    </select>

//    集合

    <select id="queryBookByForeach" resultType="mybatis01.model.Book">
      select <include refid="Base_Column_List"/> from t_book where 1=1 and book_id in(
      <foreach collection="ids" item="id" separator=",">
        #{id}
      </foreach>
      )
    </select>

4、传递多个参数

    Mapper接口
    List<Book> queryBookByParams(@Param("bookType") String bookType,@Param("bookId") Integer bookId);

    实现对应Mapper接口的xml  

  <select id="queryBookByParams" resultType="mybatis01.model.Book">
      select <include refid="Base_Column_List"/> from t_book where 1=1
      <if test="null!=bookType and ''!=bookType">
        and book_type=#{bookType}
      </if>
      <if test="null!=bookId and ''!=bookId">
        and book_id=#{bookId}
      </if>

    </select>

    这里标签里面用的是@Param定义的参数名称,不是方法的参数名称

模糊查询

   

 <select id="queryBooklike"  resultType="mybatis01.model.Book">
        select <include refid="Base_Column_List"/> from t_book where 1=1
        <if test="null!=bookType and ''!=bookType">
          and book_type like #{bookType}
        </if>
        <if test="null!=bookName and ''!=bookName">
          and book_name like '%${bookName}%'
        </if>
        <if test="null!=bookId and ''!=bookId">
          and book_Id like  concat('%',#{bookId},'%')
        </if>
     
      </select>

三种方式:

#{}:相当于占位符,参数传递时需要手动拼接%%

${}:使用$传递时,只传递参数本身, 例如: "zs"--> ${} --> zs

参数类型为字符串,#会在前后加单引号['],$则直接插入值

问题使用${...}代替#{...}(不建议使用该方式,有Sql注入风险)

concat():为数据库的拼接方法

查询返回结果集

resultMap:适合使用返回值是自定义实体类的情况
resultType:适合使用返回值的数据类型是非自定义的,即JDK的提供类型

    Mapper接口
     List<Book> queryMap();
    Book queryBookByID(Integer bookId);
    //Map和List<Map>集合适用于多表联查返回综合数据结果
    Map<String,Object> querySingBookByMap(Integer bookId);
    List<Map<String,Object>> querySingBookByMaps();
     
     
    实现对应Mapper接口的xml
    

<select id="queryMap" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/> from t_book
      </select>
      <select id="queryBookByID" resultType="mybatis01.model.Book">
        select <include refid="Base_Column_List"/> from t_book where 1=1 and book_id=#{value}
      </select>
      <select id="querySingBookByMap" resultType="java.util.Map">
        select <include refid="Base_Column_List"/> from t_book where 1=1 and book_id=#{bookId}
     
      </select>
      <select id="querySingBookByMaps" resultType="java.util.Map">
        select <include refid="Base_Column_List"/> from t_book
      </select>
</select>

分页查询

分页查询

为什么要重写mybatis的分页?
   Mybatis的分页功能很弱,它是基于内存的分页(查出所有记录再按偏移量offset和边界limit取结果),在大数据量的情况下这样的分页基本上是没有用的


 在pom.xml文件导入分页插件

 

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

将pagehelper插件配置到mybatis的核心配置文件中

   

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

    Mapper接口

    List<Book> queryBookPager(Book book);

    实现对应Mapper接口的xml

   

<select id="queryBookPager" resultType="mybatis01.model.Book">
      select <include refid="Base_Column_List"/> from t_book where 1=1
      <if test="null!=bookType and ''!=bookType">
        and book_type like concat('%',#{bookType},'%')
      </if>
      <if test="null!=bookName and ''!=bookName">
        and book_name like concat('%',#{bookName},'%')
      </if>
      order by book_Id desc
    </select>

    无需写分页的Sql语句

导入分页帮助PageBean.java工具类

分页测试

   

PageBean pageBean=new PageBean();
            pageBean.setPage(2);
     
            //判断是否分页
            if (null != pageBean && pageBean.isPagination()) {
                // 参数1:当前页码,参数2:每页条数
                PageHelper.startPage(pageBean.getPage(), pageBean.getRows());
            }
     
     
            List<Book> bookList = bookService.queryBookPager(Book.builder().bookName("西游").build(), pageBean);
            System.out.println(bookList.getClass());
     
            if (null != pageBean && pageBean.isPagination()) {
                PageInfo pageInfo = new PageInfo(bookList);
                System.out.println("页码:" + pageInfo.getPageNum());
                System.out.println("页大小:" + pageInfo.getPageSize());
                System.out.println("总记录:" + pageInfo.getTotal());
                List list = pageInfo.getList();
                list.forEach(System.out::println);
            }

范围查询,转义字符处理

    >(>)   
    <(<)  
    &(&)
 空格( )

    Bookvo属性

    private List<Integer> ids;
    private Float min;

    private Float max;    Mapper接口
    示例七:范围查询,转义字符处理
 

   List<Book> queryBookRange(BookVo bookvo);

    实现对应Mapper接口的xml
    <select id="queryBookRange" resultType="mybatis01.model.Book">
      select <include refid="Base_Column_List"/> from t_book where 1=1
      <if test="null!=min and ''!=min">
        and book_price &gt;  #{min}
      </if>
      <if test="null!=max and ''!=max">
        and book_price &lt; #{max}
      </if>
    </select>

最后给一个方便使用对象赋值的一个插件

导入lombok插件

  

  <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.22</version>
      <scope>provided</scope>
    </dependency>

之后在实体类上写入注解        

 加入@Builder之后

    Book.builder().bookId(1).build();

    赋值在builder()和build();之间如

    Book.builder().bookId(1).bookName("1").build();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值