mybatis分页设置方法(mybatis-plus分页方法)
sinye56 2024-09-19 02:21 4 浏览 0 评论
分页拦截器PageInterceptor
import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.executor.statement.RoutingStatementHandler; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.plugin.*; import org.apache.ibatis.scripting.defaults.DefaultParameterHandler; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.Properties; /** * 分页拦截器,用于拦截需要进行分页查询的操作,然后对其进行分页处理 * */ @Intercepts({ @Signature(method = "prepare", type = StatementHandler.class, args = { Connection.class }) }) public class PageInterceptor implements Interceptor { private String databaseType;// 数据库类型,不同的数据库有不同的分页方法 /** * 拦截后要执行的方法 */ public Object intercept(Invocation invocation) throws Throwable { RoutingStatementHandler handler = (RoutingStatementHandler) invocation .getTarget(); StatementHandler delegate = (StatementHandler) ReflectUtil .getFieldValue(handler, "delegate"); BoundSql boundSql = delegate.getBoundSql(); Object paramObj = boundSql.getParameterObject(); // 判断参数里是否有page对象 Pagination page = null; if (paramObj instanceof Pagination) { page = (Pagination) paramObj; } else if (paramObj instanceof Map) { for (Object arg : ((Map) paramObj).values()) { if (arg instanceof Page<?>) { page = (Pagination) arg; break; } } } if (page != null) { MappedStatement mappedStatement = (MappedStatement) ReflectUtil .getFieldValue(delegate, "mappedStatement"); Connection connection = (Connection) invocation.getArgs()[0]; String sql = boundSql.getSql(); if (page.getTotalCount() < 0) { // 如果总数为负数表需要设置 this.setTotalRecord(paramObj, mappedStatement, connection, page); } // 获取分页Sql语句 String pageSql = this.getPageSql(page, sql); // 利用反射设置当前BoundSql对应的sql属性为我们建立好的分页Sql语句 ReflectUtil.setFieldValue(boundSql, "sql", pageSql); } return invocation.proceed(); } /** * 拦截器对应的封装原始对象的方法 */ public Object plugin(Object target) { return Plugin.wrap(target, this); } /** * 设置注册拦截器时设定的属性 */ public void setProperties(Properties properties) { this.databaseType = properties.getProperty("databaseType"); } /** * 根据page对象获取对应的分页查询Sql语句,这里只做了两种数据库类型,Mysql和Oracle 其它的数据库都 没有进行分页 * * @param page * 分页对象 * @param sql * 原sql语句 * @return */ private String getPageSql(Pagination page, String sql) { StringBuffer sqlBuffer = new StringBuffer(sql); if ("mysql".equalsIgnoreCase(databaseType)) { return getMysqlPageSql(page, sqlBuffer); } else if ("oracle".equalsIgnoreCase(databaseType)) { return getOraclePageSql(page, sqlBuffer); } return sqlBuffer.toString(); } /** * 获取Mysql数据库的分页查询语句 * * @param page * 分页对象 * @param sqlBuffer * 包含原sql语句的StringBuffer对象 * @return Mysql数据库分页语句 */ private String getMysqlPageSql(Pagination page, StringBuffer sqlBuffer) { // 计算第一条记录的位置,Mysql中记录的位置是从0开始的。 int offset = (page.getPageNo() - 1) * page.getPageCount(); sqlBuffer.append(" limit ").append(offset).append(",") .append(page.getPageCount()); return sqlBuffer.toString(); } /** * 获取Oracle数据库的分页查询语句 * * @param page * 分页对象 * @param sqlBuffer * 包含原sql语句的StringBuffer对象 * @return Oracle数据库的分页查询语句 */ private String getOraclePageSql(Pagination page, StringBuffer sqlBuffer) { // 计算第一条记录的位置,Oracle分页是通过rownum进行的,而rownum是从1开始的 int offset = (page.getPageNo() - 1) * page.getPageCount() + 1; sqlBuffer.insert(0, "select u.*, rownum _rownum from (") .append(") u where rownum < ") .append(offset + page.getPageCount()); sqlBuffer.insert(0, "select * from (").append(") where _rownum >= ") .append(offset); // 上面的Sql语句拼接之后大概是这个样子: // select * from (select u.*, rownum r from (select * from t_user) u // where rownum < 31) where r >= 16 return sqlBuffer.toString(); } /** * 给当前的参数对象page设置总记录数 * * @param obj * Mapper映射语句对应的参数对象 * @param mappedStatement * Mapper映射语句 * @param connection * 当前的数据库连接 */ private void setTotalRecord(Object obj, MappedStatement mappedStatement, Connection connection, Pagination page) { BoundSql boundSql = mappedStatement.getBoundSql(obj); String sql = boundSql.getSql(); String countSql = this.getCountSql(sql); List<ParameterMapping> parameterMappings = boundSql .getParameterMappings(); BoundSql countBoundSql = new BoundSql( mappedStatement.getConfiguration(), countSql, parameterMappings, obj); ReflectUtil.setFieldValue(countBoundSql, "additionalParameters", ReflectUtil.getFieldValue(boundSql, "additionalParameters")); ReflectUtil.setFieldValue(countBoundSql, "metaParameters", ReflectUtil.getFieldValue(boundSql, "metaParameters")); ParameterHandler parameterHandler = new DefaultParameterHandler( mappedStatement, obj, countBoundSql); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = connection.prepareStatement(countSql); parameterHandler.setParameters(pstmt); rs = pstmt.executeQuery(); if (rs.next()) { int totalRecord = rs.getInt(1); // 给当前的参数page对象设置总记录数 page.setTotalCount(totalRecord); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rs != null) rs.close(); if (pstmt != null) pstmt.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 根据原Sql语句获取对应的查询总记录数的Sql语句 * * @param sql * @return */ private String getCountSql(String sql) { return "select count(1) from (" + sql + ") _tmp"; } /** * 利用反射进行操作的一个工具类 * */ private static class ReflectUtil { /** * 利用反射获取指定对象的指定属性 * * @param obj * 目标对象 * @param fieldName * 目标属性 * @return 目标属性的值 */ public static Object getFieldValue(Object obj, String fieldName) { Object result = null; Field field = ReflectUtil.getField(obj, fieldName); if (field != null) { field.setAccessible(true); try { result = field.get(obj); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return result; } /** * 利用反射获取指定对象里面的指定属性 * * @param obj * 目标对象 * @param fieldName * 目标属性 * @return 目标字段 */ private static Field getField(Object obj, String fieldName) { Field field = null; for (Class<?> clazz = obj.getClass(); clazz != Object.class; clazz = clazz .getSuperclass()) { try { field = clazz.getDeclaredField(fieldName); break; } catch (NoSuchFieldException e) { // 这里不用做处理,子类没有该字段可能对应的父类有,都没有就返回null。 } } return field; } /** * 利用反射设置指定对象的指定属性为指定的值 * * @param obj * 目标对象 * @param fieldName * 目标属性 * @param fieldValue * 目标值 */ public static void setFieldValue(Object obj, String fieldName, String fieldValue) { Field field = ReflectUtil.getField(obj, fieldName); if (field != null) { try { field.setAccessible(true); field.set(obj, fieldValue); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 利用反射设置指定对象的指定属性为指定的值 * * @param obj * 目标对象 * @param fieldName * 目标属性 * @param fieldValue * 目标值 */ public static void setFieldValue(Object obj, String fieldName, Object fieldValue) { Field field = ReflectUtil.getField(obj, fieldName); if (field != null) { try { field.setAccessible(true); field.set(obj, fieldValue); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } public String getDatabaseType() { return databaseType; } public void setDatabaseType(String databaseType) { this.databaseType = databaseType; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
配置分页拦截器
import com.yuntu.commons.mybatispage.*; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; /** */ @Configuration @MapperScan("com.yuntu.core.repository") @EnableTransactionManagement public class MybatisConfig { private static final String MYBATIS_CONFIG_FILE = "mybatis-config.xml"; /** * 注册datasource,通过@ConfigurationProperties(prefix="c3p0")将properties文件中c3p0开头的属性map到datasource相应的属性上 * @return */ @Bean @ConfigurationProperties(prefix="c3p0") public ComboPooledDataSource dataSource() { return new ComboPooledDataSource(); } @Bean(name = "sqlSessionFactory") public SqlSessionFactory sqlSessionFactoryBean() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource()); sqlSessionFactoryBean.setTypeAliasesPackage("com.friday.core.model"); sqlSessionFactoryBean.setConfigLocation(new ClassPathResource(MYBATIS_CONFIG_FILE)); PageInterceptor pageInterceptor = new PageInterceptor(); pageInterceptor.setDatabaseType("mysql"); sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageInterceptor}); return sqlSessionFactoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
其他支持类:
import java.util.List; /** * 分页基本实现 * @param <T> */ public class Page<T> implements Pagination { /** 页码 */ protected int pageNo; /** 每页记录条数 */ protected int pageCount; /** 总页数 */ protected int totalPage; /** 总记录条数 */ protected int totalCount = -1; /** 用于存放查询结果 */ protected List<T> resultList; public Page() {} public Page(Integer pageNo, int pageCount) { if(pageNo==null){ pageNo=1; } if (pageNo <= 0) { pageNo=1; //throw new IllegalArgumentException("pageNo must be greater than 0."); } if (pageCount<=0 && pageCount>50) { pageCount=50; //throw new IllegalArgumentException("pageCount must be greater than 0."); } this.pageNo = pageNo; this.pageCount = pageCount; } public void setPageNo(int pageNo) { this.pageNo = pageNo; } public void setPageCount(int pageCount) { this.pageCount = pageCount; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } public int getPageNo() { return pageNo; } public int getPageCount() { return pageCount; } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; if (totalCount < 0) { // 如果总数为负数, 表未设置 totalPage = 0; } else { // 计算总页数 totalPage = (totalCount / pageCount) + (totalCount % pageCount == 0 ? 0 : 1); } } public List<T> getResultList() { return resultList; } public void setResultList(List<T> resultList) { this.resultList = resultList; } public int getTotalPage() { return totalPage; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 /** * 分页,在分页挡截中使用 * */ public interface Pagination { /** * @return 当前页码 */ int getPageNo(); /** * @return 每页记录数 */ int getPageCount(); /** * @return 总记录数: 负数表尚未设置, 挡截器会使用count语句统计总数; 0或正整数表总数已设置, 挡截器将不会统计总数. */ int getTotalCount(); /** * @param totalCount 设置记录总数 */ void setTotalCount(int totalCount); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
使用:
在mapper接口中:
List<LibraryBookResult> getLibraryStatics(@Param("libraryBooksDto") LibraryBooksCollectDto libraryBooksDto, Pagination pagination); 1 2
在mapper.xml中不用关心分页情况
相关推荐
- Linux两种光驱自动挂载的方法
-
环境:CentOS6.4西昆云服务器方式一修改fstab文件/etc/fstab是系统保存文件系统信息?静态文件,每一行描述一个文件系统;系统每次启动会读取此文件信息以确定需要挂载哪些文件系统。参...
- linux系统运维,挂载和分区概念太难?在虚机下操作一次全掌握
-
虚拟机的好处就是可以模拟和学习生产环境的一切操作,假如我们还不熟悉磁盘操作,那先在虚机环境下多操作几次。这次来练习下硬盘扩容操作。虚拟机环境:centos8vm11linux设备命名规则在linux中...
- Linux 挂载 NFS 外部存储 (mount 和 /etc/fstab)
-
mount:手工挂载,下次重启需再重新挂载,操作命令:mount-tnfs-ooptionsserver:/remote/export/local/directory上面命令中,本地目录...
- 在Linux中如何设置自动挂载特定文件系统(示例)
-
Linux...
- Linux环境中的绑定挂载(bind mount)
-
简介:Linux中的mount命令是一个特殊的指令,主要用于挂载文件目录。而绑定挂载(bindmount)命令更为特别。mount的bind选项将第一个目录克隆到第二个。一个目录中的改变将会在...
- Linux挂载CIFS共享 临时挂载 1. 首先
-
如何解决服务器存储空间不足的问题?大家好,欢迎回来。在上一期视频中,我为大家介绍了如何利用Linux挂载来扩容服务器存储空间。这一期视频,我将以Linux为例,教大家如何进行扩容。群辉使用的是Linu...
- Linux 硬盘挂载(服务器重启自动挂载)
-
1、先查看目前机器上有几块硬盘,及已挂载磁盘:fdisk-l能够查看到当前主机上已连接上的磁盘,以及已经分割的磁盘分区。(下面以/dev/vdb磁盘进行分区、挂载为例,挂载点设置为/data)df...
- linux 挂载磁盘
-
在Linux中挂载硬盘的步骤如下:...
- 笨小猪教您Linux磁盘挂载
-
本教程针对Linux系统比较熟悉或者想学习Linux基础的用户朋友,本教程操作起来比较傻瓜式,跟着步骤就会操作,本文使用的工具是XShell同时多多注意空格(文中会有提示)。【问答】什么是磁盘挂载?答...
- Linux 磁盘挂载和docker安装命令
-
本篇给大家介绍Linux磁盘挂载和docker安装的相关内容,Linux服务器的操作是一个手熟的过程,一些不常用的命令隔断时间就忘记了,熟话说好记性不如烂笔头,还需在平时的工作中多练习记录。...
- Linux设置开机自动挂载分区
-
有时候,我们在安装完Linux系统之后,可能在使用过程中添加硬盘或者分区进行使用,这时候就需要手动把磁盘分区挂载到某个路径,但是开机之后就会消失,需要重新挂载,非常麻烦,那么我们应该如何设置开机自动挂...
- 在linux挂载一个新硬盘的完整步骤
-
以下是在Linux中挂载新原始磁盘的完整步骤,包括分区、创建文件系统以及使用UUID在/etc/fstab中启动时挂载磁盘:将新的原始磁盘连接到Linux系统并打开电源。运行以下命令,...
- Linux系统如何挂载exFAT分区
-
简介:Linux系统中不能像Windows系统那样自动识别加载新设备,需要手动识别,手动加载。Linux中一切皆文件。文件通过一个很大的文件树来组织,文件树的根目录是:/,从根目开始录逐级展开。这些文...
- Linux系统挂载硬盘
-
fdisk-l查看可挂载的磁盘都有哪些df-h查看已经挂载的磁盘...
- WSL2发布,如何在Win10中挂载Linux文件系统
-
WSL2是最新版本的架构,它为Windows子系统提供支持,使其能够在Windows上运行ELF64Linux二进制文件。通过最近的更新,它允许使用Linux文件系统访问存储在硬盘中的文件。如果你...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle忘记用户名密码 (59)
- oracle11gr2安装教程 (55)
- mybatis调用oracle存储过程 (67)
- oracle spool的用法 (57)
- oracle asm 磁盘管理 (67)
- 前端 设计模式 (64)
- 前端面试vue (56)
- linux格式化 (55)
- linux图形界面 (62)
- linux文件压缩 (75)
- Linux设置权限 (53)
- linux服务器配置 (62)
- mysql安装linux (71)
- linux启动命令 (59)
- 查看linux磁盘 (72)
- linux用户组 (74)
- linux多线程 (70)
- linux设备驱动 (53)
- linux自启动 (59)
- linux网络命令 (55)
- linux传文件 (60)
- linux打包文件 (58)
- linux查看数据库 (61)
- linux获取ip (64)
- 关闭防火墙linux (53)