mybatis之动态sql,模糊查询,结果集处理,mybatis分页及特殊字符处理

转载请标明出处:https://blog.csdn.net/men_ma/article/details/106847165.
本文出自 不怕报错 就怕不报错的小猿猿 的博客

目标及项目目录结构

目标

1、mybatis动态sql
2、模糊查询
3、查询返回结果集的处理
4、分页查询
5、特殊字符处理

项目的目录结构

在这里插入图片描述

1.mybatis动态sql

If、trim、foreach

1.1 if、trim标签(了解即可)

trim是用来去空格用的,if是用来判断属性是否为空,是否要拼接sql语句

 <insert id="insertSelective" parameterType="com.xiaoqing.model.Book" >
    insert into t_mvc_book
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="bid != null" >
        bid,
      </if>
      <if test="bname != null" >
        bname,
      </if>
      <if test="price != null" >
        price,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="bid != null" >
        #{bid,jdbcType=INTEGER},
      </if>
      <if test="bname != null" >
        #{bname,jdbcType=VARCHAR},
      </if>
      <if test="price != null" >
        #{price,jdbcType=REAL},
      </if>
    </trim>
  </insert>

1.2 foreach标签(测试此标签效果的流程)

第一步 :BookMapper.java中的方法:

/*测试foreach标签方法的dao层*/
List<Book> selectBooksIn(@Param("bookIds") List bookIds);

第二步 :BookMapper.xml中的配置标签:

parameterType:参数的类型
collection:参数的变量
item :遍历的指针
open:左开区间打开
close:右开区间关闭
separator:中间的分隔符
#{bid}:指针的值

  <!--讲解foreach 标签-->
  <select id="selectBooksIn" resultType="com.xiaoqing.model.Book" parameterType="java.util.List">
    select * from t_mvc_book where bid in
    <foreach collection="bookIds" item="bid" open="(" close=")" separator=",">
      #{bid}
    </foreach>
  </select>

第三步 :加入方法到BookService.java接口类中:

/*测试foreach标签方法的业务逻辑层*/
    List<Book> selectBooksIn(List bookIds);

第四步 :在BookServiceImpl.java实现类中实现此方法:

 @Override
    public List<Book> selectBooksIn(List bookIds) {
        return bookMapper.selectBooksIn(bookIds);
    }

第五步 :在BookServiceImplTest.java测试类中测试此方法:

/*测试foreach标签的测试方法*/
   @Test
    public void selectBooksIn(){
        List bookIds=new ArrayList();
        bookIds.add(1);
        bookIds.add(4);
        bookIds.add(5);
        for (Book book : this.bookService.selectBooksIn(bookIds)) {
            System.out.println(book);
        }
    }

第六步 :数据库中的数据
在这里插入图片描述
第七步 :测试的结果:查询bid编号为1,4,5的数据信息
在这里插入图片描述

2.模糊查询

2.1 语法

第一种形式:#{…}(常用)
第二种形式:${…}(动态列需要用到,比如下拉框查询,按价格或者作者这些列字段进行查询)
第三种形式:Concat

注意:#{…}自带引号,${…}有sql注入的风险

2.2 做一个案例

第一步 :BookMapper.java中的方法:

  /*测试模糊查询方法一:#{...}形式*/
    List<Book> selectBookLike1(@Param("bname")String bname);
    /*测试模糊查询方法二:${…}形式*/
    List<Book> selectBookLike2(@Param("bname")String bname);
    /*测试模糊查询方法三:Concat形式*/
    List<Book> selectBookLike3(@Param("bname")String bname);

第二步 :BookMapper.xml中的配置标签:

<!--测试模糊查询方法一:#{...}形式-->
  <select id="selectBookLike1" resultType="com.xiaoqing.model.Book" parameterType="java.lang.String">
    select * from t_mvc_book
    <where>
      bname like #{bname}
    </where>
  </select>
  <!--测试模糊查询方法二:${…}形式 需要带引号-->
  <select id="selectBookLike2" resultType="com.xiaoqing.model.Book" parameterType="java.lang.String">
    select * from t_mvc_book
    <where>
      bname like '${bname}'
    </where>
  </select>
  <!--测试模糊查询方法三:Concat形式-->
  <select id="selectBookLike3" resultType="com.xiaoqing.model.Book" parameterType="java.lang.String">
    select * from t_mvc_book
    <where>
      bname like concat('%',#{bname},'%')
    </where>
  </select>

第三步 :加入方法到BookService.java接口类中:

    List<Book> selectBookLike1(String bname);

    List<Book> selectBookLike2(String bname);

    List<Book> selectBookLike3(String bname);

第四步 :在BookServiceImpl.java实现类中实现此方法:

@Override
    public List<Book> selectBookLike1(String bname) {
        return bookMapper.selectBookLike1(bname);
    }

    @Override
    public List<Book> selectBookLike2(String bname) {
        return bookMapper.selectBookLike2(bname);
    }

    @Override
    public List<Book> selectBookLike3(String bname) {
        return bookMapper.selectBookLike3(bname);
    }

第五步 :在BookServiceImplTest.java测试类中测试此方法:

 /*测试模糊查询的三种形式*/
    @Test
    public void selectBookLike(){
        /*for (Book book : this.bookService.selectBookLike1("%而%")) {
            System.out.println(book);
        }*/

        /*for (Book book : this.bookService.selectBookLike2("%而%")) {
            System.out.println(book);
        }*/

        for (Book book : this.bookService.selectBookLike3("而")) {
            System.out.println(book);
        }
    }

第六步 :数据库中的数据
在这里插入图片描述
第七步 :测试的结果:查询bname书名中含有“而”字的数据信息
在这里插入图片描述

3.查询返回结果集的处理

3.1 语法

resultMap

适合使用返回值是自定义实体类的情况(可以理解为将实体类进行了二次包装和处理)

resultType

适合使用返回值的数据类型是非自定义的,即jdk的提供的类型(可以理解为是自己写的实体类没有经过任何的包装和处理的)

3.1.1 使用resultMap返回自定义类型集合

3.1.2 使用resultType返回List<T>

3.1.3 使用resultType返回单个对象

3.1.4 使用resultType返回List<Map>,适用于多表查询返回结果集

3.1.5 使用resultType返回Map<String,Object>,适用于多表查询返回单个结果集

3.2 案例(用来测试)

首先再建一个BookVo(V:view,o:object)实体类用于多表查询返回一个集合:

/**
 * @author 晴sister
 * @site https://blog.csdn.net/men_ma
 * @company
 * @create 2020-10-1020:21
 *
 * vo类专门用来封装多表联查信息用于展示的
 * 也可用于封装查询条件
 */
public class BookVo extends  Book{
    private List<Integer> bookIds;
    public List<Integer> getBookIds() {
        return bookIds;
    }

    public void setBookIds(List<Integer> bookIds) {
        this.bookIds = bookIds;
    }
}

第一步 :BookMapper.java中的方法:

 /*查询多条数据返回的是map自定义集合:使用resultMap返回自定义类型集合*/
    List<Book> list1();
    /* 使用resultType返回List<T>*/
    List<Book> list2();
    /*使用resultType返回Map<String,Object>,适用于多表查询返回单个结果集*/
    List<Book> list3(BookVo bookVo);
    /*直接返回map集合,有多少个键都可取,常用*/
    List<Map> list4();
    /*查询单个结果集,常用*/
    Map list5(Map map);

第二步 :BookMapper.xml中的配置标签:

 <select id="list1" resultMap="BaseResultMap">
    select * from t_mvc_book
  </select>
  <select id="list2" resultType="com.xiaoqing.model.Book">
    select * from t_mvc_book
  </select>
  <select id="list3" resultType="com.xiaoqing.model.Book" parameterType="com.xiaoqing.model.BookVo">
    select * from t_mvc_book where bid in
    <foreach collection="bookIds" item="bid" open="(" close=")" separator=",">
      #{bid}
    </foreach>
  </select>
  <select id="list4" resultType="java.util.Map">
     select * from t_mvc_book
  </select>
  <select id="list5" resultType="java.util.Map" parameterType="java.util.Map">
    select * from t_mvc_book where bid = #{bid}
  </select>

第三步 :加入方法到BookService.java接口类中:

 	 List<Book> list1();
    List<Book> list2();
    List<Book> list3(BookVo bookVo);
    List<Map> list4();
    Map list5(Map map);

第四步 :在BookServiceImpl.java实现类中实现此方法:

 @Override
    public List<Book> list1() {
        return bookMapper.list1();
    }

    @Override
    public List<Book> list2() {
        return bookMapper.list2();
    }

    @Override
    public List<Book> list3(BookVo bookVo) {
        return bookMapper.list3(bookVo);
    }

    @Override
    public List<Map> list4() {
        return bookMapper.list4();
    }

    @Override
    public Map list5(Map map) {
        return bookMapper.list5(map);
    }

第五步 :在BookServiceImplTest.java测试类中测试此方法:

 @Test
    public void list1(){
        for (Book book : this.bookService.list1()) {
            System.out.println(book);
        }
    }
    @Test
    public void list2(){
        for (Book book : this.bookService.list2()) {
            System.out.println(book);
        }
    }
    @Test
    public void list3(){
        BookVo bookVo=new BookVo();
        List bookIds=new ArrayList();
        bookIds.add(6);
        bookIds.add(9);
        bookIds.add(4);
        bookVo.setBookIds(bookIds);
        for (Book book : this.bookService.list3(bookVo)) {
            System.out.println(book);
        }
    }
    @Test
    public void list4(){//常用
        for (Map map : this.bookService.list4()) {
            System.out.println(map);
        }
    }
    @Test
    public void list5(){//常用
        Map map=new HashMap();
        map.put("bid",6);
        System.out.println(this.bookService.list5(map));
    }

第六步 :数据库中的数据
在这里插入图片描述
第七步 :测试的结果:查询各个结果集的数据信息
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.分页查询

4.1 语法

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

使用分页插件步奏
1、导入pom依赖
2、Mybatis.cfg.xml配置拦截器
3、使用PageHelper进行分页
4、处理分页结果

4.2 分页的准备工作

Pom依赖:

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

Mybatis.cfg.xml配置拦截器:一定要注意先后顺序

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

在这里插入图片描述
pageBean的工具类:

package com.xiaoqing.utils;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

/**
 * 分页工具类
 *
 */
public class PageBean {

	private int page = 1;// 当前页码

	private int rows = 5;// 页大小

	private int total = 0;//总记录数

	//上一次查询的url
	private String url;
	//上一次查询所携带的查询条件
	private Map<String, String[]> parameterMap=new HashMap<String, String[]>();
	
	//对pagebean进行初始化
	public void setRequest(HttpServletRequest req) {
		//初始化jsp页面传递过来的当前页
		this.setPage(req.getParameter("page"));
		//初始化jsp页面传递过来的页大小
		this.setRows(req.getParameter("rows"));
		//初始化jsp页面 传递过来是否分页
		this.setPagination(req.getParameter("pagination"));
		//保留上一次的查询请求
		this.setUrl(req.getRequestURL().toString());
		//保留上一次的查询条件
		this.setParameterMap(req.getParameterMap());
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public Map<String, String[]> getParameterMap() {
		return parameterMap;
	}
	public void setParameterMap(Map<String, String[]> parameterMap) {
		this.parameterMap = parameterMap;
	}
	private void setPage(String page) {
		if(StringUtils.isNotBlank(page)) {
			this.setPage(Integer.valueOf(page));
		}
	}
	private void setRows(String rows) {
		if(StringUtils.isNotBlank(rows)) {
			this.setRows(Integer.valueOf(rows));
		}
	}
	private void setPagination(String pagination) {
		//只有填了false字符串,才代表不分页
			this.setPagination(!"false".equals(pagination));;
	}
	
	private boolean pagination = true;// 是否分页

	public PageBean() {
		super();
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public int getRows() {
		return rows;
	}

	public void setRows(int rows) {
		this.rows = 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 pagination;
	}

	public void setPagination(boolean pagination) {
		this.pagination = pagination;
	}

	/**
	 * 获得起始记录的下标
	 * 
	 * @return
	 */
	public int getStartIndex() {
		return (this.page - 1) * this.rows;
	}

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

	//上一页
	public int getPrevPage() {
		return this.page>1?this.page-1:this.page;
	}
	//下一页
	public int getNextPage() {
		return this.page<this.getMaxPage()?this.page+1:this.page;
	}
	//最大页
	public int getMaxPage() {
		return this.total%this.rows==0?this.total/this.rows:(this.total/this.rows)+1;
	}
	
	
}

StringUtils工具类:附属pagebean工具类

package com.xiaoqing.utils;

public class StringUtils {
	// 私有的构造方法,保护此类不能在外部实例化
	private StringUtils() {
	}

	/**
	 * 如果字符串等于null或去空格后等于"",则返回true,否则返回false
	 * 
	 * @param s
	 * @return
	 */
	public static boolean isBlank(String s) {
		boolean b = false;
		if (null == s || s.trim().equals("")) {
			b = true;
		}
		return b;
	}
	
	/**
	 * 如果字符串不等于null或去空格后不等于"",则返回true,否则返回false
	 * 
	 * @param s
	 * @return
	 */
	public static boolean isNotBlank(String s) {
		return !isBlank(s);
	}

}

4.3 案例(测试)

第一步 :BookMapper.java中的方法:

//    select * from t_mvc_book where bname like '%而%' limit 20,10
    List<Map> listPager(Map map);

**第二步 :BookMapper.xml中的配置标签:
**


  <select id="listPager" resultType="java.util.Map" parameterType="java.util.Map">
    select * from t_mvc_book
    <where>
      <if test="bname!=null and bname!=''">
        bname like #{bname}
      </if>
    </where>
  </select>

第三步 :加入方法到BookService.java接口类中:

   List<Map> listPager(Map map, PageBean pageBean);

第四步 :在BookServiceImpl.java实现类中实现此方法:

  @Override
    public List<Map> listPager(Map map, PageBean pageBean) {
        //利用环绕通知 =前置通知+目标+后置通知
//        前置通知
        if(pageBean!=null&&pageBean.isPagination()){
            PageHelper.startPage(pageBean.getPage(),pageBean.getRows());
        }
//        环绕通知的目标
        List<Map> list=bookMapper.listPager(map);
//        后置通知
        if(pageBean!=null&&pageBean.isPagination()){
            PageInfo pageInfo=new PageInfo(list);
            System.out.println("当前页:" + pageInfo.getPageNum());
            System.out.println("显示当前内容数量::" + pageInfo.getPageSize());
            System.out.println("符合条件的总记录数::" + pageInfo.getTotal());
//            用于下一次分页
            pageBean.setTotal(pageInfo.getTotal()+"");
        }
        return list;
    }

第五步 :在BookServiceImplTest.java测试类中测试此方法:

  @Test
    public void listPager(){
        Map map=new HashMap();
        map.put("bname","%而%");
        PageBean pageBean=new PageBean();
//        设置是否分页
//        pageBean.setPagination(false);
//        查询第几页的数据
        pageBean.setPage(2);
        for (Map m : this.bookService.listPager(map, pageBean)) {
            System.out.println(m);
        }
    }

第六步 :数据库中的数据
在这里插入图片描述

第七步 :测试的结果:查询分页效果的数据信息
在这里插入图片描述

5.特殊字符处理

5.1 语法

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

<![CDATA[ <= ]]>

5.2 准备工作(BookVo.java实体类添加两个属性)

package com.xiaoqing.model;

import java.util.List;

/**
 * @author 晴sister
 * @site https://blog.csdn.net/men_ma
 * @company
 * @create 2020-10-1020:21
 *
 * vo类专门用来封装多表联查信息用于展示的
 * 也可用于封装查询条件
 */
public class BookVo extends  Book{
    private List<Integer> bookIds;
    private Float min;
    private Float max;

    public Float getMin() {
        return min;
    }

    public void setMin(Float min) {
        this.min = min;
    }

    public Float getMax() {
        return max;
    }

    public void setMax(Float max) {
        this.max = max;
    }
    public List<Integer> getBookIds() {
        return bookIds;
    }

    public void setBookIds(List<Integer> bookIds) {
        this.bookIds = bookIds;
    }
}

5.3 案例(测试)

第一步 :BookMapper.java中的方法:

    List<Book> list6(BookVo bookVo);

第二步 :BookMapper.xml中的配置标签:
两种形式,注释了一种 测试时替换一下就好了

<!--或者是 select * from t_mvc_book where <![CDATA[ price >#{min} and price <#{max} ]]>-->
  <select id="list6" resultType="com.xiaoqing.model.Book" parameterType="com.xiaoqing.model.BookVo">
      select * from t_mvc_book where price &gt; #{min} and price &lt; #{max}
  </select>

第三步 :加入方法到BookService.java接口类中:

  List<Book> list6(BookVo bookVo);

第四步 :在BookServiceImpl.java实现类中实现此方法:

 @Override
    public List<Book> list6(BookVo bookVo) {
        return bookMapper.list6(bookVo);
    }

第五步 :在BookServiceImplTest.java测试类中测试此方法:

 @Test
    public void list6(){
        BookVo bookVo=new BookVo();
        bookVo.setMax(35f);
        bookVo.setMin(21f);
        for (Book book : this.bookService.list6(bookVo)) {
            System.out.println(book);
        }
    }

第六步 :数据库中的数据
在这里插入图片描述
第七步 :测试的结果:查询特殊字符处理的数据信息

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值