MyBatis拦截器实现分页功能实例

 更新时间:2017年04月19日 17:17:32   作者:jethypc  
本篇文章主要介绍了MyBatis拦截器实现分页功能实例,这里整理了详细的代码,有需要的小伙伴可以参考下。

由于业务关系 巴拉巴拉巴拉

好吧 简单来说就是

原来的业务是 需要再实现类里写 selectCount 和selectPage两个方法才能实现分页功能

现在想要达到效果是 只通过一个方法就可以实现 也就是功能合并 所以就有了下面的实践

既然是基于MyBatis 所以就先搭建一个Mybatis的小项目

1.01导入 mybatis和mysql的包

1.02.配置文件 Configuration.xml 中添加

 <environments default="development">
  <environment id="development">
  <transactionManager type="JDBC"/>
   <dataSource type="POOLED">
   <property name="driver" value="com.mysql.jdbc.Driver"/>
   <property name="url" value="jdbc:mysql://localhost:3306/test" />
   <property name="username" value="root"/>
   <property name="password" value=""/>
   </dataSource>
  </environment>
 </environments>

2.01.然后创建一个模块user  创建user表

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` char(32) NOT NULL,
 `t1` char(32) DEFAULT NULL,
 `t2` char(32) DEFAULT NULL,
 `t3` char(32) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

3.01.写对应bean:User.java

package lqb.bean;

public class User extends Common{

 private String id;
 private String name;
 private String t1;
 private String t2;
 private String t3;

 //省略get set 
}

3.02.对应的mapper: UserMapper.java和UserMapper.xml 

简单实现下CRUD

public interface UserMapper {
 public User selectByID(int id);
 public List<User> select();
 public int insert(User u);
 public int update(User u);
 public int delete(User u);
 
}
<mapper namespace="lqb.mapper.UserMapper">
 <select id="selectByID" parameterType="int" resultType="lqb.bean.User">
  select * from `user` where id = #{id}
 </select>
 <select id="select" resultType="lqb.bean.User" parameterType="lqb.bean.User">
  select * from `user` 
 </select>
 
 <insert id="insert" parameterType="lqb.bean.User">
  insert into user (id,name,t1,t2,t3) values (#{id},#{name},#{t1},#{t2},#{t3})
 </insert>
 <update id="update" parameterType="lqb.bean.User">
  update user set name=#{name},t1=#{t1},t2=#{t2},t3=#{t3} where id=#{id}
 </update>
 <delete id="delete" parameterType="lqb.bean.User">
  delete from user where id=#{id}
 </delete>
</mapper>

3.03.然后 在配置文件Configuration.xml中添加user的配置

<mappers>
  <mapper resource="lqb/mapper/UserMapper.xml"/>
</mappers>

3.04.然后是实现:UserService.java

public class UserService {
 private static SqlSessionFactory sqlSessionFactory;
 private static Reader reader;

 static{
  try{
   reader = Resources.getResourceAsReader("Configuration.xml");
   sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
  }catch(Exception e){
   e.printStackTrace();
  }
 }

 public static SqlSessionFactory getSession(){
  return sqlSessionFactory;
 }
}

4.01 好 然后是重点了

思路: 截获查询的sql 然后拼成 sqlPage和sqlCount 再进行查找取值 然后赋传入对象

所以我们就需要创建一个基础类来让user.java来继承

public class Common {
 private int pagesize;
 private int pageid;
 private int pagebegin;
 private int count;
 //省略 get set 
}

4.02 然后 让User继承Common

public class User extends Common{

4.03 那怎么截获sql呢 我们就要写一个mybatis的拦截器 用来拦截sql请求 PageInterceptor

 @Intercepts({
  @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}), 
  @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
}) 
public class PageInterceptor implements Interceptor { 
  //插件运行的代码,它将代替原有的方法
 @Override
 public Object intercept(Invocation invocation) throws Throwable {
 }
 
 // 拦截类型StatementHandler 
 @Override
 public Object plugin(Object target) {
 }
 
 @Override
 public void setProperties(Properties properties) {  
 } 

4.04 首先 设置拦截类型 重写plugin方法

@Override
 public Object plugin(Object target) {
  if (target instanceof StatementHandler) { 
   return Plugin.wrap(target, this); 
  } else { 
   return target; 
  } 
 }

4.05 然后 就要重写最重要的intercept了

这里我们有一个设定  如果查询方法含有searchpage 就进行分页 其他方法无视

所以就要获取方法名

 StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); 
 MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler); 
 MappedStatement mappedStatement=(MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
 String selectId=mappedStatement.getId();

4.06 然后判断下 如果含有searchpage 就获取sql

BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql"); 
// 分页参数作为参数对象parameterObject的一个属性 
String sql = boundSql.getSql();
Common co=(Common)(boundSql.getParameterObject());

4.07 然后 根据这个sql 重新拼写countsql和pagesql

String countSql=concatCountSql(sql);
String pageSql=concatPageSql(sql,co);
...
public String concatCountSql(String sql){
  StringBuffer sb=new StringBuffer("select count(*) from ");
  sql=sql.toLowerCase();
  
  if(sql.lastIndexOf("order")>sql.lastIndexOf(")")){
   sb.append(sql.substring(sql.indexOf("from")+4, sql.lastIndexOf("order")));
  }else{
   sb.append(sql.substring(sql.indexOf("from")+4));
  }
  return sb.toString();
 }
 
public String concatPageSql(String sql,Common co){
  StringBuffer sb=new StringBuffer();
  sb.append(sql);
  sb.append(" limit ").append(co.getPagebegin()).append(" , ").append(co.getPagesize());
  return sb.toString();
 }

4.08 然后 通过jdbc查询count 然后把值绑定给common

 Connection connection = (Connection) invocation.getArgs()[0]; 
    
    PreparedStatement countStmt = null; 
    ResultSet rs = null; 
    int totalCount = 0; 
    try { 
     countStmt = connection.prepareStatement(countSql); 
     rs = countStmt.executeQuery(); 
     if (rs.next()) { 
      totalCount = rs.getInt(1); 
     } 
     
    } catch (SQLException e) { 
     System.out.println("Ignore this exception"+e); 
    } finally { 
     try { 
      rs.close(); 
      countStmt.close(); 
     } catch (SQLException e) { 
      System.out.println("Ignore this exception"+ e); 
     } 
    } 
    
      
    
    //绑定count
    co.setCount(totalCount);

4.09 再把pagesql赋给元BoundSql

metaStatementHandler.setValue("delegate.boundSql.sql", pageSql); 

4.10 最后在配置文件中添加拦截器配置

 <plugins> 
 <plugin interceptor="lqb.interceptor.PageInterceptor"/>
</plugins> 

4.11 好然后 在UserMapper.java和UserMapper.xml中添加分页代码

 <select id="selectPage" parameterType="lqb.bean.User" resultType="lqb.bean.User">
  select * from `user` where id in(3,4,6,8) order by id
 </select>
public List<User> selectPage(User u);

5.01 最后是测试了

main...请允许本人的懒 就姑且在main方法测下吧

User u=new User();
u.setPagebegin(2);
u.setPagesize(3);
System.out.println("-u.getCount()------"+u.getCount());
List<User> l=userService.selectPage(u);
System.out.println(l.size());
System.out.println("-u.getCount()------"+u.getCount());

5.02 结果 略   然后就成功了 

 下面附上拦截器的代码

package lqb.interceptor;

import java.util.Properties;
import org.apache.ibatis.executor.resultset.ResultSetHandler; 
import org.apache.ibatis.executor.statement.StatementHandler; 
import org.apache.ibatis.mapping.BoundSql; 
import org.apache.ibatis.mapping.MappedStatement; 
import org.apache.ibatis.plugin.*; 
import org.apache.ibatis.reflection.MetaObject; 
import org.apache.ibatis.reflection.SystemMetaObject; 
import java.sql.*; 
import lqb.bean.Common;

@Intercepts({
  @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}), 
  @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
}) 
public class PageInterceptor implements Interceptor { 
 
 private static final String SELECT_ID="selectpage";


 //插件运行的代码,它将代替原有的方法
 @Override
 public Object intercept(Invocation invocation) throws Throwable {
  System.out.println("PageInterceptor -- intercept");
  
  
  if (invocation.getTarget() instanceof StatementHandler) { 
   StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); 
   MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler); 
   MappedStatement mappedStatement=(MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
   String selectId=mappedStatement.getId();
   
   if(SELECT_ID.equals(selectId.substring(selectId.lastIndexOf(".")+1).toLowerCase())){
    BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql"); 
    // 分页参数作为参数对象parameterObject的一个属性 
    String sql = boundSql.getSql();
    Common co=(Common)(boundSql.getParameterObject());
    
    // 重写sql 
    String countSql=concatCountSql(sql);
    String pageSql=concatPageSql(sql,co);
    
    System.out.println("重写的 count sql  :"+countSql);
    System.out.println("重写的 select sql  :"+pageSql);
    
    Connection connection = (Connection) invocation.getArgs()[0]; 
    
    PreparedStatement countStmt = null; 
    ResultSet rs = null; 
    int totalCount = 0; 
    try { 
     countStmt = connection.prepareStatement(countSql); 
     rs = countStmt.executeQuery(); 
     if (rs.next()) { 
      totalCount = rs.getInt(1); 
     } 
     
    } catch (SQLException e) { 
     System.out.println("Ignore this exception"+e); 
    } finally { 
     try { 
      rs.close(); 
      countStmt.close(); 
     } catch (SQLException e) { 
      System.out.println("Ignore this exception"+ e); 
     } 
    } 
    
    metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);   
    
    //绑定count
    co.setCount(totalCount);
   }
  } 
  
  return invocation.proceed();
 }
 
 /**
  * 拦截类型StatementHandler 
  */
 @Override
 public Object plugin(Object target) {
  if (target instanceof StatementHandler) { 
   return Plugin.wrap(target, this); 
  } else { 
   return target; 
  } 
 }
 
 @Override
 public void setProperties(Properties properties) {
  
 } 
 
 
 public String concatCountSql(String sql){
  StringBuffer sb=new StringBuffer("select count(*) from ");
  sql=sql.toLowerCase();
  
  if(sql.lastIndexOf("order")>sql.lastIndexOf(")")){
   sb.append(sql.substring(sql.indexOf("from")+4, sql.lastIndexOf("order")));
  }else{
   sb.append(sql.substring(sql.indexOf("from")+4));
  }
  return sb.toString();
 }
 
 public String concatPageSql(String sql,Common co){
  StringBuffer sb=new StringBuffer();
  sb.append(sql);
  sb.append(" limit ").append(co.getPagebegin()).append(" , ").append(co.getPagesize());
  return sb.toString();
 }
 
 public void setPageCount(){
  
 }
 
}

最后是下载地址:mybatisResolve_jb51.rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 浅谈JavaAPI 中 <E> 与 <T> 的含义

    浅谈JavaAPI 中 <E> 与 <T> 的含义

    下面小编就为大家带来一篇浅谈JavaAPI 中 <E> 与 <T> 的含义。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • java中String.intern()方法功能介绍

    java中String.intern()方法功能介绍

    这篇文章主要介绍了java中String.intern()方法具有什么功能,主要包括String.intern原理,JDK6中String.intern()的相关知识,本文给大家介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • Java中的String对象数据类型全面解析

    Java中的String对象数据类型全面解析

    首先String不属于8种基本数据类型,String是一个对象,因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性
    2012-11-11
  • 深入理解java重载和重写

    深入理解java重载和重写

    这篇文章主要介绍了Java方法重载和重写原理区别解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2021-07-07
  • 关于Spring的@Transaction导致数据库回滚全部生效问题(又删库跑路)

    关于Spring的@Transaction导致数据库回滚全部生效问题(又删库跑路)

    使用@Transactional一键开启声明式事务, 这就真的事务生效了?过于信任框架总有“意外惊喜”。本文通过案例给大家详解关于Spring的@Transaction导致数据库回滚全部生效问题,感兴趣的朋友一起看看吧
    2021-05-05
  • Springmvc 4.x利用@ResponseBody返回Json数据的方法

    Springmvc 4.x利用@ResponseBody返回Json数据的方法

    这篇文章主要介绍了Springmvc 4.x利用@ResponseBody返回Json数据的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • Springboot jdbctemplate整合实现步骤解析

    Springboot jdbctemplate整合实现步骤解析

    这篇文章主要介绍了Springboot jdbctemplate整合实现步骤解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • MybatisPlus中QueryWrapper常用方法总结

    MybatisPlus中QueryWrapper常用方法总结

    MyBatis-Plus是一个Mybatis增强版工具,在MyBatis上扩充了其他功能没有改变其基本功能,为了简化开发提交效率而存在,queryWrapper是mybatis plus中实现查询的对象封装操作类,本文就给大家总结了MybatisPlus中QueryWrapper的常用方法,需要的朋友可以参考下
    2023-07-07
  • Java内存溢出案例模拟和原理分析过程

    Java内存溢出案例模拟和原理分析过程

    这篇文章主要介绍了Java内存溢出案例模拟和原理分析过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • Spring Cache优化数据库访问的项目实践

    Spring Cache优化数据库访问的项目实践

    本文主要介绍了Spring Cache优化数据库访问的项目实践,将创建一个简单的图书管理应用作为示例,并演示如何通过缓存减少对数据库的频繁查询,感兴趣的可以了解一下
    2024-01-01

最新评论