- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章MyBatis实现物理分页的实例由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
MyBatis使用RowBounds实现的分页是逻辑分页,也就是先把数据记录全部查询出来,然在再根据offset和limit截断记录返回 。
为了在数据库层面上实现物理分页,又不改变原来MyBatis的函数逻辑,可以编写plugin截获MyBatis Executor的statementhandler,重写SQL来执行查询 。
下面的插件代码只针对MySQL 。
plugin代码 。
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
|
package
plugin;
import
java.sql.Connection;
import
java.sql.PreparedStatement;
import
java.sql.ResultSet;
import
java.sql.SQLException;
import
java.util.Properties;
import
org.apache.ibatis.executor.parameter.ParameterHandler;
import
org.apache.ibatis.executor.statement.StatementHandler;
import
org.apache.ibatis.logging.Log;
import
org.apache.ibatis.logging.LogFactory;
import
org.apache.ibatis.mapping.BoundSql;
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.factory.DefaultObjectFactory;
import
org.apache.ibatis.reflection.factory.ObjectFactory;
import
org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import
org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import
org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import
org.apache.ibatis.session.Configuration;
import
org.apache.ibatis.session.RowBounds;
/**
* 通过拦截<code>StatementHandler</code>的<code>prepare</code>方法,重写sql语句实现物理分页。
* 老规矩,签名里要拦截的类型只能是接口。
*
*/
@Intercepts
({
@Signature
(type = StatementHandler.
class
, method =
"prepare"
, args = {Connection.
class
})})
public
class
PaginationInterceptor
implements
Interceptor {
private
static
final
Log logger = LogFactory.getLog(PaginationInterceptor.
class
);
private
static
final
ObjectFactory DEFAULT_OBJECT_FACTORY =
new
DefaultObjectFactory();
private
static
final
ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY =
new
DefaultObjectWrapperFactory();
private
static
String DEFAULT_PAGE_SQL_ID =
".*Page$"
;
// 需要拦截的ID(正则匹配)
@Override
public
Object intercept(Invocation invocation)
throws
Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY,
DEFAULT_OBJECT_WRAPPER_FACTORY);
RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue(
"delegate.rowBounds"
);
// 分离代理对象链(由于目标类可能被多个拦截器拦截,从而形成多次代理,通过下面的两次循环可以分离出最原始的的目标类)
while
(metaStatementHandler.hasGetter(
"h"
)) {
Object object = metaStatementHandler.getValue(
"h"
);
metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
}
// 分离最后一个代理对象的目标类
while
(metaStatementHandler.hasGetter(
"target"
)) {
Object object = metaStatementHandler.getValue(
"target"
);
metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
}
// property在mybatis settings文件内配置
Configuration configuration = (Configuration) metaStatementHandler.getValue(
"delegate.configuration"
);
// 设置pageSqlId
String pageSqlId = configuration.getVariables().getProperty(
"pageSqlId"
);
if
(
null
== pageSqlId ||
""
.equals(pageSqlId)) {
logger.warn(
"Property pageSqlId is not setted,use default '.*Page$' "
);
pageSqlId = DEFAULT_PAGE_SQL_ID;
}
MappedStatement mappedStatement = (MappedStatement)
metaStatementHandler.getValue(
"delegate.mappedStatement"
);
// 只重写需要分页的sql语句。通过MappedStatement的ID匹配,默认重写以Page结尾的MappedStatement的sql
if
(mappedStatement.getId().matches(pageSqlId)) {
BoundSql boundSql = (BoundSql) metaStatementHandler.getValue(
"delegate.boundSql"
);
Object parameterObject = boundSql.getParameterObject();
if
(parameterObject ==
null
) {
throw
new
NullPointerException(
"parameterObject is null!"
);
}
else
{
String sql = boundSql.getSql();
// 重写sql
String pageSql = sql +
" LIMIT "
+ rowBounds.getOffset() +
","
+ rowBounds.getLimit();
metaStatementHandler.setValue(
"delegate.boundSql.sql"
, pageSql);
// 采用物理分页后,就不需要mybatis的内存分页了,所以重置下面的两个参数
metaStatementHandler.setValue(
"delegate.rowBounds.offset"
, RowBounds.NO_ROW_OFFSET);
metaStatementHandler.setValue(
"delegate.rowBounds.limit"
, RowBounds.NO_ROW_LIMIT);
}
}
// 将执行权交给下一个拦截器
return
invocation.proceed();
}
@Override
public
Object plugin(Object target) {
// 当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的次数
if
(target
instanceof
StatementHandler) {
return
Plugin.wrap(target,
this
);
}
else
{
return
target;
}
}
@Override
public
void
setProperties(Properties properties) {
//To change body of implemented methods use File | Settings | File Templates.
}
}
|
配置plugin 。
1
2
3
|
<
plugins
>
<
plugin
interceptor
=
"plugin.PaginationInterceptor"
/>
</
plugins
>
|
查询SQL 。
1
2
3
4
5
6
|
<!-- 测试分页查询 -->
<
select
id
=
"selectUserByPage"
resultMap
=
"dao.base.userResultMap"
>
<![CDATA[
SELECT * FROM user
]]>
</
select
>
|
调用示例 。
1
2
3
4
5
|
@Override
public
List<User> selectUserByPage(
int
offset,
int
limit) {
RowBounds rowBounds =
new
RowBounds(offset, limit);
return
getSqlSession().selectList(
"dao.userdao.selectUserByPage"
,
new
Object(), rowBounds);
}
|
另外,结合Spring MVC,编写翻页和生成页码代码 。
页码类 。
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
|
package
util;
/**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-7
* Time: 上午10:29
* To change this template use File | Settings | File Templates.
*/
public
class
Pagination {
private
String url;
// 页码url
private
int
pageSize =
10
;
// 每页显示记录数
private
int
currentPage =
1
;
// 当前页码
private
int
maxPage = Integer.MAX_VALUE;
// 最大页数
// 获取offset
public
int
getOffset() {
return
(currentPage -
1
) * pageSize;
}
// 获取limit
public
int
getLimit() {
return
getPageSize();
}
public
String getUrl() {
return
url;
}
public
void
setUrl(String url) {
this
.url = url;
}
public
int
getPageSize() {
return
pageSize;
}
public
void
setPageSize(
int
pageSize) {
this
.pageSize = pageSize;
}
public
int
getCurrentPage() {
return
currentPage;
}
public
void
setCurrentPage(
int
currentPage) {
if
(currentPage <
1
)
currentPage =
1
;
if
(currentPage > maxPage)
currentPage = maxPage;
this
.currentPage = currentPage;
}
public
int
getMaxPage() {
return
maxPage;
}
public
void
setMaxPage(
int
maxPage) {
this
.maxPage = maxPage;
}
}
|
为了计算最大页码,需要知道数据表的总记录数,查询SQL如下 。
1
2
3
4
5
6
|
<!-- 记录总数 -->
<
select
id
=
"countUser"
resultType
=
"Integer"
>
<![CDATA[
SELECT COUNT(*) FROM user
]]>
</
select
>
|
1
2
3
4
|
@Override
public
Integer countTable() {
return
getSqlSession().selectOne(
"dao.userdao.countUser"
);
}
|
Controller中的使用 。
1
2
3
4
5
6
7
8
9
10
11
12
|
@RequestMapping
(
"/getUserByPage"
)
public
String getUserByPage(
@RequestParam
int
page, Model model) {
pagination.setCurrentPage(page);
pagination.setUrl(getCurrentUrl());
pagination.setMaxPage(userDao.countTable() / pagination.getPageSize() +
1
);
List<User> userList = userDao.selectUserByPage(
pagination.getOffset(), pagination.getLimit());
model.addAttribute(pagination);
model.addAttribute(userList);
return
"index"
;
}
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:http://www.cnblogs.com/zemliu/archive/2013/08/07/3242966.html 。
最后此篇关于MyBatis实现物理分页的实例的文章就讲到这里了,如果你想了解更多关于MyBatis实现物理分页的实例的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我一直在寻找游戏/模拟解决方案,以便在时间流逝时寻找距离,但这不是我要找的。 我正在寻找一个 O(1) 公式来计算(0 或 1 或 2)时钟时间,其中两个圆圈彼此之间的距离恰好为 r1+r2。负时间是
我究竟做错了什么? > crossprod(1:3,4:6) [,1] [1,] 32 根据本网站:http://onlinemschool.com/math/assistance/ve
嗨,我目前正在为类开发一个迷你游戏(第一次做这样的事情),我根本不知道如何开始碰撞检测。好吧,我正在创建的游戏是一款在冰冷的圆形竞技场上自上而下的相扑格斗游戏,您可以四处移动以获得动力和速度,并尝试击
这段代码取自使用 XNA 框架构建的游戏。我想从三角学和物理学的角度解释一下它是如何工作的。 ball.velocity = new Vector2((float)Math.Cos(cannon.ro
因此,我正在努力自学 Canvas (HTML5) 并编写了大部分简单的游戏引擎代码。它是空间场景(行星、恒星、天体等)的二维表示。我的默认“Sprite”类有一个像这样的帧监听器: “baseCla
这个问题在这里已经有了答案: Are the physical memory addresses of an array also stored in order like the virtual o
我正在尝试阅读英特尔软件开发人员手册以了解操作系统的工作原理,这四个寻址术语让我感到困惑。以上是我的理解,如有不对请指正。 线性地址 : 对一个孤立的程序来说,似乎是一长串以地址0开头的内存。该程序的
我尝试在 AndEngine 示例包中复制并粘贴物理示例。 没有出现错误,但当我运行它时,模拟器显示“不幸的是,PhysicsActivity 已停止”。 模拟器使用 API 15,GPU 已开启,磁
当我运行此代码时,第一行 CollisionWithplayer 给了我一个错误的指令错误。该错误不会每次都会出现,只是偶尔出现一次,并且没有类似的条件来确定导致该错误的原因。 func didBeg
您好,我有以下 Canvas 应用程序:http://dev.driz.co.uk/canvas/ 正如您将看到的,它渲染了一堆球。我遇到的问题是当应用程序首次启动时,球被 Canvas 边缘切断。他
我有两个 3d 物理 vector ,带有 (x,y,z) 和方向。我想对它们做一些操作。但我有一些问题: 我应该如何在 C++ 中表示这个 vector ?换句话说,我在下面写了类,但我不知道如何表
我有一个有 body 的 Sprite 。我想通过路径移动 Sprite 。我已经尝试使用 PathModifier 执行此操作, Sprite 会按原样移动,但它的 body 不会跟随 Sprite
我开发了类似投币推土机的游戏。为了硬币的平稳移动,我为每个硬币添加了一种物理 Material ,但这样做之后我的游戏速度非常慢。有没有其他选择,或者我如何在不使用物理 Material 的情况下使硬
我正在开发一款简单的平台游戏,例如 super 马里奥。我将 Java 与 LibGdx 引擎一起使用。我的物理问题与帧率无关。在我的游戏中,角色可以跳跃,跳跃高度显然取决于帧率。 在我的桌面上,游戏
我正在开发一个可能包含数学、物理和化学符号的问答应用程序,因为这是一个实时游戏应用程序,每次问题将从服务器下载并针对特定主题显示。它需要是一个原生的 Android 应用程序,并且性能非常重要(两人游
我的任务是编写一个对象,该对象可以接收不同类型的路径/url,并返回它是什么类型的路径/url。例如路径可以是 1. [drive]:\Temp 2. \\Temp 3. Temp (assuming
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
注意:当我提到层时,我指的是物理层。此站点上与“层”相关的许多问题都指的是逻辑层,这不是我要问的。 我正在设计一个使用标准“3 层”架构的应用程序,包括表示层、业务逻辑 (BLL) 层和数据访问层 (
如何检查设备上的屏幕或物理/电容式导航按钮 最佳答案 您可以使用 ViewConfiguration.get(context).hasPermanentMenuKey() 仅适用于 API 级别 14
我在我的 android 游戏中使用 AndEngine,我从 github 下载了主 AndEngine,但是没有主的 Physics Box2D 扩展。我不知道在哪里下载它或我可以使用它的哪个版本
我是一名优秀的程序员,十分优秀!