百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

mybatis分页设置方法(mybatis-plus分页方法)

sinye56 2024-09-19 02:21 8 浏览 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中不用关心分页情况

相关推荐

程序员:JDK的安装与配置(完整版)_jdk的安装方法

对于Java程序员来说,jdk是必不陌生的一个词。但怎么安装配置jdk,对新手来说确实头疼的一件事情。我这里以jdk10为例,详细的说明讲解了jdk的安装和配置,如果有不明白的小伙伴可以评论区留言哦下...

Linux中安装jdk并配置环境变量_linux jdk安装教程及环境变量配置

一、通过连接工具登录到Linux(我这里使用的Centos7.6版本)服务器连接工具有很多我就不一一介绍了今天使用比较常用的XShell工具登录成功如下:二、上传jdk安装包到Linux服务器jdk...

麒麟系统安装JAVA JDK教程_麒麟系统配置jdk

检查检查系统是否自带java在麒麟系统桌面空白处,右键“在终端打开”,打开shell对话框输入:java–version查看是否自带java及版本如图所示,系统自带OpenJDK,要先卸载自带JDK...

学习笔记-Linux JDK - 安装&amp;配置

前提条件#检查是否存在JDKrpm-qa|grepjava#删除现存JDKyum-yremovejava*安装OracleJDK不分系统#进入安装文件目...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

测试员必备:Linux下安装JDK 1.8你必须知道的那些事

1.简介在Oracle收购Sun后,Java的一系列产品就被整合到Oracle官网中,打开官网乍眼一看也不知道去哪里下载,还得一个一个的摸索尝试,而且网上大多数都是一些Oracle收购Sun前,或者就...

Linux 下安装JDK17_linux 安装jdk1.8 yum

一、安装环境操作系统:JDK版本:17二、安装步骤第一步:下载安装包下载Linux环境下的jdk1.8,请去官网(https://www.oracle.com/java/technologies/do...

在Ubuntu系统中安装JDK 17并配置环境变量教程

在Ubuntu系统上安装JDK17并配置环境变量是Java开发环境搭建的重要步骤。JDK17是Oracle提供的长期支持版本,广泛用于开发Java应用程序。以下是详细的步骤,帮助你在Ubuntu系...

如何在 Linux 上安装 Java_linux安装java的步骤

在桌面上拥抱Java应用程序,然后在所有桌面上运行它们。--SethKenlon(作者)无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序...

Windows和Linux环境下的JDK安装教程

JavaDevelopmentKit(简称JDK),是Java开发的核心工具包,提供了Java应用程序的编译、运行和开发所需的各类工具和类库。它包括了JRE(JavaRuntimeEnviro...

linux安装jdk_linux安装jdk软连接

JDK是啥就不用多介绍了哈,外行的人也不会进来看我的博文。依然记得读大学那会,第一次实验课就是在机房安装jdk,编写HelloWorld程序。时光飞逝啊,一下过了十多年了,挣了不少钱,买了跑车,娶了富...

linux安装jdk,全局配置,不同用户不同jdk

jdk1.8安装包链接:https://pan.baidu.com/s/14qBrh6ZpLK04QS8ogCepwg提取码:09zs上传文件解压tar-zxvfjdk-8u152-linux-...

运维大神教你在linux下安装jdk8_linux安装jdk1.7

1.到官网下载适合自己机器的版本。楼主下载的是jdk-8u66-linux-i586.tar.gzhttp://www.oracle.com/technetwork/java/javase/downl...

window和linux安装JDK1.8_linux 安装jdk1.8.tar

Windows安装JDK1.8的步骤:步骤1:下载JDK打开浏览器,找到JDK下载页面https://d.injdk.cn/download/oraclejdk/8在页面中找到并点击“下载...

最全的linux下安装JavaJDK的教程(图文详解)不会安装你来打我?

默认已经有了linux服务器,且有root账号首先检查一下是否已经安装过java的jdk任意位置输入命令:whichjava像我这个已经安装过了,就会提示在哪个位置,你的肯定是找不到。一般我们在...

取消回复欢迎 发表评论: