Mybatis 之 动态sql&分页

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_44641053/article/details/101067867

Mybatis 动态SQL & 分页

本章知识点:

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


  1. 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+"%";
				    }
				}

  1. 模糊查询

    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 ,如果传入的值是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;
				
				}

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

    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>

分页查询

  1. 分页查询

    为什么要重写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>

特殊字符串处理

  1. 特殊字符处理

     			>(&gt;)   
     			
     		    <(&lt;)  
     		    
     		    &(&amp;) 
     		    
     	       空格(&nbsp;)
     		 
     		 <![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} &lt; price
    			      </if>
    			      <if test="null != max and max != ''">
    			        and #{max} &gt; price
    			      </if>
    			    </where>
    			  </select>
    			
    

猜你喜欢

转载自blog.csdn.net/qq_44641053/article/details/101067867