MyBatis 拦截器 (实现分页功能)
由于业务关系 巴拉巴拉巴拉
好吧 简单来说就是
原来的业务是 需要再实现类里写 selectCount 和selectPage两个方法才能实现分页功能
现在想要达到效果是 只通过一个方法就可以实现 也就是功能合并 所以就有了下面的实践
既然是基于MyBatis 所以就先搭建一个Mybatis的小项目
1.01导入 mybatis和mysql的包
aaarticlea/png;base64,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" alt="" />
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(){ } }
最后是下载地址
MyBatis 拦截器 (实现分页功能)的更多相关文章
- mybatis拦截器实现分页功能的示例讲解
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import jav ...
- Mybatis拦截器实现分页
本文介绍使用Mybatis拦截器,实现分页:并且在dao层,直接返回自定义的分页对象. 最终dao层结果: public interface ModelMapper { Page<Model&g ...
- MyBatis拦截器自定义分页插件实现
MyBaits是一个开源的优秀的持久层框架,SQL语句与代码分离,面向配置的编程,良好支持复杂数据映射,动态SQL;MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyB ...
- Mybatis拦截器介绍及分页插件
1.1 目录 1.1 目录 1.2 前言 1.3 Interceptor接口 1.4 注册拦截器 1.5 Mybatis可拦截的方法 1.6 利用拦截器进行分页 1.2 前言 拦截器的一 ...
- MyBatis拦截器原理探究
MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允 ...
- Mybatis拦截器介绍
拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法.Mybatis拦截器设计的一个初 ...
- 【Mybatis】1、Mybatis拦截器学习资料汇总
MyBatis拦截器原理探究 http://www.cnblogs.com/fangjian0423/p/mybatis-interceptor.html [myBatis]Mybatis中的拦截器 ...
- 【公众号转载】MyBatis拦截器原理探究
MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允 ...
- mybatis拦截器使用
目录 mybatis 拦截器接口Interceptor spring boot + mybatis整合 创建自己的拦截器MyInterceptor @Intercepts注解 mybatis拦截器入门 ...
- Mybatis拦截器实现原理深度分析
1.拦截器简介 拦截器可以说使我们平时开发经常用到的技术了,Spring AOP.Mybatis自定义插件原理都是基于拦截器实现的,而拦截器又是以动态代理为基础实现的,每个框架对拦截器的实现不完全相同 ...
随机推荐
- hdoj 2553 N皇后问题【回溯+打表】
N皇后问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- vijos 1464 NOIP 1997 积木游戏
背景 1997年全国青少年信息学(计算机)奥林匹克竞赛试题 第二试 描述 积木游戏 SERCOI 最近设计了一种积木游戏.每个游戏者有N块编号依次为1 ,2,…,N的长方体积木.对于每块积木,它的三条 ...
- cocos2d-x简单动画
转自:http://4137613.blog.51cto.com/4127613/759610 这里只给出最基本的动画代码,具体使用要根据实际情况自己封装.最好自己开发一个编辑器.额外说一句,开发编辑 ...
- [转]非常好的vsftpd安装于配置
环境:CentOS 5.0 操作系统一.安装:1.安装Vsftpd服务相关部件:[root@KcentOS5 ~]# yum install vsftpd*Dependencies Resolved= ...
- Java凝视Override、Deprecated、SuppressWarnings具体解释
一.什么是凝视 说起凝视,得先提一提什么是元数据(metadata).所谓元数据就是数据的数据.也就是说,元数据是描写叙述数据的.就象数据表中的字段一样,每一个字段描写叙述了这个字段下的数据的 ...
- 【剑指Offer学习】【面试题19 :二叉树的镜像】
题目:请完毕一个函数,输入一个二叉树,该函数输出它的镜像. 二叉树结点的定义: /** * 二叉树的树结点 */ public static class BinaryTreeNode { int va ...
- 从div盒子模型谈如何写可维护的css代码(转)
市面上我们常常会看到各种各样的设计模式书籍,Java设计模式.C#设计模式.Ruby设计模式等等.在众多的语言设计模式中我唯独找不到关于CSS设计模式的资料,即使在网上找到类似内容,细细一看之下才发觉 ...
- Android_Component_example
xml布局: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:t ...
- html5标签兼容ie6,7,8
注册博客园已经三年了,这三年一直在忙,没时间写博文.也许是忙,也许是懒吧!当然这三年发生了很多事,我也从开发人员转变为前端人员. 是时候对所学的,所用的知识做一下沉淀了.就从这一篇开始吧! html5 ...
- c语言,strcat(),字符串拼接
#include<stdio.h> #include<string.h> int main() { char destination[25]; char *zhang=& ...