幾種常見mybatis分頁實(shí)現(xiàn)方式
幾種常見mybatis分頁實(shí)現(xiàn)
mybatis框架分頁實(shí)現(xiàn),有幾種方式,最簡單的就是利用原生的sql關(guān)鍵字limit來實(shí)現(xiàn),還有一種就是利用interceptor來拼接sql,實(shí)現(xiàn)和limit一樣的功能,再一個就是利用PageHelper來實(shí)現(xiàn)。
這里講解這三種常見的實(shí)現(xiàn)方式:
無論哪種實(shí)現(xiàn)方式,我們返回的結(jié)果,不能再使用List了,需要一個自定義對象Pager。
package com.xxx.mybatis.bean; import java.util.List; public class Pager<T> { private int page;//分頁起始頁 private int size;//每頁記錄數(shù) private List<T> rows;//返回的記錄集合 private long total;//總記錄條數(shù) public int getPage() { return page; } public void setPage(int page) { this.page = page; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } public List<T> getRows() { return rows; } public void setRows(List<T> rows) { this.rows = rows; } public long getTotal() { return total; } public void setTotal(long total) { this.total = total; } }
limit關(guān)鍵字實(shí)現(xiàn)
UserDao.java增加兩個方法
public List<User> findByPager(Map<String, Object> params); public long count();
UserMapper.xml中增加兩個查詢
<select id="findByPager" resultType="com.xxx.mybatis.domain.User"> select * from xx_user limit #{page},#{size} </select> <select id="count" resultType="long"> select count(1) from xx_user </select>
UserService.java中增加分頁方法
public Pager<User> findByPager(int page,int size){ Map<String, Object> params = new HashMap<String, Object>(); params.put("page", (page-1)*size); params.put("size", size); Pager<User> pager = new Pager<User>(); List<User> list = userDao.findByPager(params); pager.setRows(list); pager.setTotal(userDao.count()); return pager; }
這是最直觀的實(shí)現(xiàn)方式,也是最簡單的,不用任何插件或者工具就能夠很方便的實(shí)現(xiàn)的方法。
interceptor plugin實(shí)現(xiàn)
需要定義一個類實(shí)現(xiàn)Interceptor接口
MyPageInterceptor.java
package com.xxx.mybatis.bean; import java.sql.Connection; import java.util.Map; import java.util.Properties; import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; @Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class,Integer.class})}) public class MyPageInterceptor implements Interceptor { private int page; private int size; @SuppressWarnings("unused") private String dbType; @SuppressWarnings("unchecked") @Override public Object intercept(Invocation invocation) throws Throwable { System.out.println("plugin is running..."); StatementHandler statementHandler = (StatementHandler)invocation.getTarget(); MetaObject metaObject = SystemMetaObject.forObject(statementHandler); while(metaObject.hasGetter("h")){ Object object = metaObject.getValue("h"); metaObject = SystemMetaObject.forObject(object); } while(metaObject.hasGetter("target")){ Object object = metaObject.getValue("target"); metaObject = SystemMetaObject.forObject(object); } MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement"); String mapId = mappedStatement.getId(); if(mapId.matches(".+ByPager$")){ ParameterHandler parameterHandler = (ParameterHandler)metaObject.getValue("delegate.parameterHandler"); Map<String, Object> params = (Map<String, Object>)parameterHandler.getParameterObject(); page = (int)params.get("page"); size = (int)params.get("size"); String sql = (String) metaObject.getValue("delegate.boundSql.sql"); sql += " limit "+(page-1)*size +","+size; metaObject.setValue("delegate.boundSql.sql", sql); } return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { String limit = properties.getProperty("limit","10"); this.page = Integer.parseInt(limit); this.dbType = properties.getProperty("dbType", "mysql"); } }
我們之前在service的findByPager方法里面,為了給limit傳入兩個參數(shù),其中page做了計(jì)算,這里使用攔截器的方式就無需計(jì)算了:
public Pager<User> findByPager(int page,int size){ Map<String, Object> params = new HashMap<String, Object>(); params.put("page", page); params.put("size", size); Pager<User> pager = new Pager<User>(); List<User> list = userDao.findByPager(params); pager.setRows(list); pager.setTotal(userDao.count()); return pager; }
spring配置中,增加plugin設(shè)置:
到這里,你也許也猜到了MyPageInterceptor實(shí)際上是以一種攔截器的方式在程序執(zhí)行findByPager方法的時候,對語句會增加limit page,size的拼接,還是和第一種原生實(shí)現(xiàn)思路一樣,所以這里需要對UserMapper.xml配置文件中的findByPager這個查詢對應(yīng)的語句中的limit #{page},#{size}這部分去掉,變?yōu)槿缦碌臉幼樱?/p>
至此,通過攔截器插件的方式也實(shí)現(xiàn)了分頁功能了。
PageHelper實(shí)現(xiàn)
這種方式實(shí)現(xiàn)需要我們引入maven依賴。
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>4.2.1</version> </dependency>
spring.xml配置文件做一下修改:
<bean id="pageInterceptor" class="com.github.pagehelper.PageHelper"> <property name="properties"> <props> <prop key="helperDialect">mysql</prop> <prop key="reasonable">true</prop> <prop key="supportMethodsArguments">true</prop> <prop key="params">count=countSql</prop> </props> </property> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations" value="classpath:com/xxx/mybatis/dao/*Mapper.xml"/> <property name="plugins" ref="pageInterceptor"></property> </bean>
service層的方法,做一些修改:
public Pager<User> findByPager(int page,int size){ Pager<User> pager = new Pager<User>(); Page<User> res = PageHelper.startPage(page,size); userDao.findAll(); pager.setRows(res.getResult()); pager.setTotal(res.getTotal()); return pager; }
至此,PageHelper工具方法實(shí)現(xiàn)分頁也實(shí)現(xiàn)了。其實(shí)PageHelper方法也是第二種使用Interceptor攔截器方式的一種三方實(shí)現(xiàn),它內(nèi)部幫助我們實(shí)現(xiàn)了Interceptor的功能。
所以我們不用自定義MyPageInterceptor這個類了。
實(shí)際上也是在運(yùn)行查詢方法的時候,進(jìn)行攔截,然后設(shè)置分頁參數(shù)。
所以PageHelper.startPage(page,size)這一句需要顯示調(diào)用,然后再執(zhí)行userDao.findAll(),在查詢所有用戶信息的時候,會進(jìn)行一個分頁參數(shù)設(shè)置,讓放回的結(jié)果只是分頁的結(jié)果,而不是全部集合。
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
解讀SpringBoot為什么要用DeferredImportSelector
這篇文章主要介紹了SpringBoot為什么要用DeferredImportSelector的情況,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-03-03springboot集成swagger、knife4j及常用注解的使用
這篇文章主要介紹了springboot集成swagger、knife4j及常用注解的使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07java 中函數(shù)的參數(shù)傳遞詳細(xì)介紹
這篇文章主要介紹了 java 中函數(shù)的參數(shù)傳遞詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2016-11-11Spring-retry實(shí)現(xiàn)循環(huán)重試功能
這篇文章主要介紹了Spring-retry 優(yōu)雅的實(shí)現(xiàn)循環(huán)重試功能,通過@Retryable注解,優(yōu)雅的實(shí)現(xiàn)循環(huán)重試功能,需要的朋友可以參考下2023-07-07