MyBatis攔截器實(shí)現(xiàn)分頁功能實(shí)例
由于業(yè)務(wù)關(guān)系 巴拉巴拉巴拉
好吧 簡單來說就是
原來的業(yè)務(wù)是 需要再實(shí)現(xiàn)類里寫 selectCount 和selectPage兩個(gè)方法才能實(shí)現(xiàn)分頁功能
現(xiàn)在想要達(dá)到效果是 只通過一個(gè)方法就可以實(shí)現(xiàn) 也就是功能合并 所以就有了下面的實(shí)踐
既然是基于MyBatis 所以就先搭建一個(gè)Mybatis的小項(xiàng)目
1.01導(dǎo)入 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.然后創(chuàng)建一個(gè)模塊user 創(chuàng)建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.寫對(duì)應(yīng)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.對(duì)應(yīng)的mapper: UserMapper.java和UserMapper.xml
簡單實(shí)現(xiàn)下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.然后是實(shí)現(xiàn):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 好 然后是重點(diǎn)了
思路: 截獲查詢的sql 然后拼成 sqlPage和sqlCount 再進(jìn)行查找取值 然后賦傳入對(duì)象
所以我們就需要?jiǎng)?chuàng)建一個(gè)基礎(chǔ)類來讓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呢 我們就要寫一個(gè)mybatis的攔截器 用來攔截sql請(qǐng)求 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 {
//插件運(yùn)行的代碼,它將代替原有的方法
@Override
public Object intercept(Invocation invocation) throws Throwable {
}
// 攔截類型StatementHandler
@Override
public Object plugin(Object target) {
}
@Override
public void setProperties(Properties properties) {
}
4.04 首先 設(shè)置攔截類型 重寫plugin方法
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
4.05 然后 就要重寫最重要的intercept了
這里我們有一個(gè)設(shè)定 如果查詢方法含有searchpage 就進(jìn)行分頁 其他方法無視
所以就要獲取方法名
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");
// 分頁參數(shù)作為參數(shù)對(duì)象parameterObject的一個(gè)屬性
String sql = boundSql.getSql();
Common co=(Common)(boundSql.getParameterObject());
4.07 然后 根據(jù)這個(gè)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...請(qǐng)?jiān)试S本人的懶 就姑且在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 結(jié)果 略 然后就成功了
下面附上攔截器的代碼
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";
//插件運(yùn)行的代碼,它將代替原有的方法
@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");
// 分頁參數(shù)作為參數(shù)對(duì)象parameterObject的一個(gè)屬性
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
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
gateway網(wǎng)關(guān)與前端請(qǐng)求跨域問題的解決方案
這篇文章主要介紹了gateway網(wǎng)關(guān)與前端請(qǐng)求跨域問題的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
徹底理解Spring注解@Autowired實(shí)現(xiàn)原理
這篇文章主要為大家詳細(xì)的介紹了Spring注解@Autowired實(shí)現(xiàn)的原理,縝密的邏輯分析,實(shí)踐應(yīng)用示例操作說明,讓大家徹底的理解Spring注解@Autowired背后實(shí)現(xiàn)原理2022-03-03
SpringBoot下獲取resources目錄下文件的常用方法
本文詳細(xì)介紹了SpringBoot獲取resources目錄下文件的常用方法,包括使用this.getClass()方法、ClassPathResource獲取以及hutool工具類ResourceUtil獲取,感興趣的可以了解一下2024-10-10
Java利用MessageFormat實(shí)現(xiàn)短信模板的匹配
這篇文章主要介紹了Java利用MessageFormat實(shí)現(xiàn)短信模板的匹配,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06
仿釘釘流程輕松實(shí)現(xiàn)JSON轉(zhuǎn)BPMN完整實(shí)現(xiàn)過程示例
這篇文章主要為大家介紹了仿釘釘流程輕松實(shí)現(xiàn)JSON轉(zhuǎn)BPMN完整實(shí)現(xiàn)過程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
springboot設(shè)置加載靜態(tài)資源的路徑(spring.resources.static-locations)
這篇文章主要介紹了springboot設(shè)置加載靜態(tài)資源的路徑方式(spring.resources.static-locations),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
Java如何獲取JSONObject內(nèi)指定字段key的value值
這篇文章主要介紹了Java如何獲取JSONObject內(nèi)指定字段key的value值問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12

