Mybatis 之 动态sql&分页
Mybatis 动态SQL & 分页
本章知识点:
1、mybatis动态sql
2、模糊查询
3、查询返回结果集的处理(重点)
4、分页查询(重点)
5、特殊字符处理
-
mybatis 动态sql
1.1 if 条件
1.2 trim 去空格
1.3 foreach
遍历集合,批量查询、通常用于 in 关键字
1.4 其他
choose/set/where
模糊查询
自定义工具类:(模糊查询所用)
package com.dj.util;
/**
* @author dj
* @company xxx公司
* @create 2019- 09 - 20 - 21:16
*/
public class StringUtil {
public static String toLikeStr(String str){
return "%"+str+"%";
}
}
-
模糊查询
2.1 参数中直接加入%%
2.2 使用 ${…} 代替 #{…}(不建议使用该方式,有SQL注入风险)
MyBatis中#和$的区别
-
# 将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by ‘111’,
如果传入的值是id,则解析成的sql为order by “id”. -
$ 将传入的数据直接显示生成在sql中。
如:order by u s e r i d user_id userid,如果传入的值是111,那么解析成sql时的值为order by user_id,
如果传入的值是id,则解析成的sql为order by id. -
# 方式能够很大程度防止sql注入。
-
$ 方式无法防止Sql注入。
-
$ 方式一般用于传入数据库对象,
例如传入表名 . 一般能用#的就别用 $.<select id="selectBylike1" resultType="com.dj.model.Article" parameterType="java.lang.String"> select * from t_vue_articles where title like #{title} </select> <select id="selectBylike2" resultType="com.dj.model.Article" parameterType="java.lang.String"> select * from t_vue_articles where title like '${title}' </select>
注意: 1) mybatis中使用OGNL表达式传递参数 2) 优先使用#{...} 3) ${...}方式存在SQL注入风险
2.3 SQL字符串拼接CONCAT
<select id="selectBylike3" resultType="com.dj.model.Article" parameterType="java.lang.String"> select * from t_vue_articles where title like concat(concat('%',#{title}),'%') </select>
测试代码:
@Test public void selectByLike() { List<Article> articles = this.articleService.selectBylike1(StringUtil.toLikeStr("欢喜")); // List<Article> articles = this.articleService.selectBylike2("%欢喜 or id !=1%"); // List<Article> articles = this.articleService.selectBylike3(title:"欢喜"); for (Article a : articles) {//articles.for + / 即可 System.out.println(a);//a.sout 即可 } }
返回结果集处理
Vo 实体类:
package com.dj.model;
import java.util.List;
/**
* @author dj
* @company xxx公司
* @create 2019- 09 - 20 - 21:48
*
* Vo类
* 用来存放数据库中表映射字段,以及多余查询条件所需属性
*
*/
public class ArticleVo {
public List<String> getId() {
return id;
}
public void setId(List<String> id) {
this.id = id;
}
private List<String> id;
}
-
查询返回结果集的处理
resultMap:适合使用返回值是自定义实体类的情况
resultType:适合使用返回值的数据类型是非自定义的,即jdk提供的类型
3.1 使用 resultMap 返回自定义类型集合
/**
* 使用resultMap返回自定义类型集合
* @return
*/
List<Article> list1();
<select id="list1" resultMap="BaseResultMap">
select * from t_vue_articles
</select>
3.2 使用 resultType 返回 List< T >
/**
* 使用resultType返回List<T>
* @return
*/
List<Article> list2();
<select id="list2" resultType="com.dj.model.Article">
select * from t_vue_articles
</select>
3.3 使用 resultType 返回单个对象
/**
* 使用resultType返回单个对象
* @return
*/
Article list3(ArticleVo articleVo);
<select id="list3" resultType="com.dj.model.Article" parameterType="com.dj.model.ArticleVo">
select * from t_vue_articles where id in
<foreach collection="id" open="(" close=")" separator="," item="id">
#{bid}
</foreach>
</select>
3.4 使用 resultType 返回List< Map >,适用于多表查询返回结果集
/**
* 使用resultType返回List<Map>,适用于多表查询返回结果集
* @return
*/
List<Map> list4();
<select id="list4" resultType="java.util.Map">
select * from t_vue_articles
</select>
3.5 使用 resultType 返回Map< String,Object >,适用于多表查询返回单个结果集
/**
* 使用resultType返回Map<String,Object>,适用于多表查询返回单个结果集
* @return
*/
Map list5(Map article);
<select id="list5" resultType="java.util.Map" parameterType="java.util.Map">
select * from t_vue_articles where bid = #{bid}
</select>
分页查询
-
分页查询
为什么要重写mybatis的分页?
Mybatis的分页功能很弱,它是基于内存的分页(查出所有记录再按偏移量offset和边界limit取结果),
在大数据量的情况下这样的分页基本上是没有用的使用分页插件步骤:
-
、导入 pom 依赖
-
、Mybatis.cfg.xml 配置拦截器
-
、使用 PageHelper 进行分页
-
、处理分页结果
-
4.1 导入 pom 依赖
导入分页插件
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
4.2 Mybatis.cfg.xml 配置拦截器
将 pagehelper 插件配置到 mybatis 中
<plugins>
<!-- 配置分页插件PageHelper, 4.0.0以后的版本支持自动识别使用的数据库 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
</plugin>
</plugins>
4.3 使用 PageHelper 进行分页
在你需要进行分页的 Mybatis 方法前,调用 PageHelper.startPage 静态方法,紧跟在这个方法后的第一个 Mybatis 查询方法会被进行分页 。
//设置分页处理
if (null != pageBean && pageBean.isPaginate()) {
PageHelper.startPage(pageBean.getCurPage(), pageBean.getPageRecord());
}
PageHelper配置详解
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 支持的方言: oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012 -->
<property name="dialect" value="mysql"/>
<!-- 该参数默认为false -->
<!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 -->
<!-- 和startPage中的pageNum效果一样-->
<property name="offsetAsPageNum" value="true"/>
<!-- 该参数默认为false -->
<!-- 设置为true时,使用RowBounds分页会进行count查询 -->
<property name="rowBoundsWithCount" value="true"/>
<!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 -->
<!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)-->
<property name="pageSizeZero" value="true"/>
<!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 -->
<!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
<!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
<property name="reasonable" value="false"/>
<!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 -->
<!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 -->
<!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,orderBy,不配置映射的用默认值 -->
<!-- 不理解该含义的前提下,不要随便复制该配置 -->
<property name="params" value="pageNum=pageHelperStart;pageSize=pageHelperRows;"/>
<!-- 支持通过Mapper接口参数来传递分页参数 -->
<property name="supportMethodsArguments" value="false"/>
<!-- always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page -->
<property name="returnPageInfo" value="none"/>
</plugin>
</plugins>
4.4 获取分页信息(二种方式)
-
4.4.1 使用插件后,查询实际返回的是Page,而非List,Page继承了ArrayList,同时还包含分页相关的信息
Page<Articles> page = (Page<Articles>)list; System.out.println("页码:" + page.getPageNum()); System.out.println("页大小:" + page.getPageSize()); System.out.println("总记录:" + page.getTotal());
-
4.4.2 使用 PageInfo
PageInfo pageInfo = new PageInfo(list); System.out.println("页码:" + pageInfo.getPageNum()); System.out.println("页大小:" + pageInfo.getPageSize()); System.out.println("总记录:" + pageInfo.getTotal());
struts 拦截器
定义一个拦截器类
invoke
sysout("action方法被调用前执行的功能")
method.invoke
sysout("action方法被调用后执行的功能")
struts-sy.xml
将拦截器的类申明到 interceptors
引用拦截器
<action>
<interceptor-ref>
使用分页插件
/**
* 分页
* @param map
* @param pageBean
* @return
*/
List<Map> listPager(Map map, PageBean pageBean);
<select id="listPager" resultType="java.util.Map" parameterType="java.util.Map">
select * from t_vue_articles where title like concat(concat('%',#{title}),'%')
</select>
特殊字符串处理
-
特殊字符处理
>(>) <(<) &(&) 空格( ) <![CDATA[ <= ]]>
/** * 处理特殊字符 * @param articleVo * @return */ List<Article> list6(ArticleVo articleVo); <select id="list6" resultType="com.dj.model.Article" parameterType="com.dj.model.ArticleVo"> select * from t_vue_article <where> <if test="null != min and min != ''"> <![CDATA[ and #{min} < price ]]> </if> <if test="null != max and max != ''"> <![CDATA[ and #{max} > price ]]> </if> </where> </select> /** * 处理特殊字符 * @param articleVo * @return */ List<Article> list7(ArticleVo articleVo); <select id="list7" resultType="com.dj.model.Article" parameterType="com.dj.model.ArticleVo"> select * from t_vue_article <where> <if test="null != min and min != ''"> and #{min} < price </if> <if test="null != max and max != ''"> and #{max} > price </if> </where> </select>