转载请标明出处:https://blog.csdn.net/men_ma/article/details/106847165.
本文出自 不怕报错 就怕不报错的小猿猿 的博客
mybatis之动态sql,模糊查询,结果集处理,mybatis分页及特殊字符处理
目标及项目目录结构
目标
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 > #{min} and price < #{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);
}
}
第六步 :数据库中的数据
第七步 :测试的结果:查询特殊字符处理的数据信息