欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-02-28 12:07:46
由于业务关系 巴拉巴拉巴拉 好吧 简单来说就是 原来的业务是 需要再实现类里写 selectcount 和selectpage两个方法才能实现分页功能 现在想要达到效...

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

好吧 简单来说就是

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

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

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

1.01导入 mybatis和mysql的包

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

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

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