MyBatis分页有3种方法:
1.直接在映射文件里写sql语句,然后传参数
2.在接口方法里加入参数 RowBounds
3.利用插件实现分页
说说各自的优缺点:
1.太麻烦了,每个要实现分页的都要写,扩展性不强 (放弃)
2.当数据库数据多的时候,效率极低,可能会出现内存溢出
3.需要自己实现interceptor接口,但是扩展性强
这里说一说分页的思路,以mysql为例子,就是用limit来实现分页
我们为了实现分页,有一种思路就是拦截StatementHandler,在其编译sql语句前把sql改成我们要的样子,然后注入参数,最后查询得到分页效果,下面上代码
1.直接在映射文件里写sql语句,然后传参数
2.在接口方法里加入参数 RowBounds
3.利用插件实现分页
说说各自的优缺点:
1.太麻烦了,每个要实现分页的都要写,扩展性不强 (放弃)
2.当数据库数据多的时候,效率极低,可能会出现内存溢出
3.需要自己实现interceptor接口,但是扩展性强
这里说一说分页的思路,以mysql为例子,就是用limit来实现分页
我们为了实现分页,有一种思路就是拦截StatementHandler,在其编译sql语句前把sql改成我们要的样子,然后注入参数,最后查询得到分页效果,下面上代码
package Model;
public class Page {
private Integer currentPage;//当前页码
private Integer pageSize;//每页总数
private Integer pageCount;//全部记录
public Integer getCurrentPage() {
return currentPage;
}
public void setCurrentPage(Integer currentPage) {
this.currentPage = currentPage;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getPageCount() {
return pageCount;
}
public void setPageCount(Integer pageCount) {
this.pageCount = pageCount;
}
@Override
public String toString() {
return "Page [currentPage=" + currentPage + ", pageSize=" + pageSize + ", pageCount=" + pageCount + "]";
}
}
package Mapper;
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.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
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;
import org.apache.log4j.Logger;
import Model.Page;
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class pageInterceptor implements Interceptor {
private Page page = null;
private Logger logger = Logger.getLogger(pageInterceptor.class);
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 获得源对象
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
// 从源对象获得属性操作类
MetaObject m1 = SystemMetaObject.forObject(statementHandler);
// 多次循环分离出原始目标类
Object object = null;
while (m1.hasGetter("h")) {
object = m1.getValue("h");
m1 = SystemMetaObject.forObject(m1);
}
if (object == null)
object = statementHandler;// 如果为空证明压根就没有代理对象,即没有插件用它,
// 获取原始目标类的属性操作类
MetaObject m2 = SystemMetaObject.forObject(object);
while (m2.hasGetter("target")) {
object = m2.getValue("target");
m2 = SystemMetaObject.forObject(object);
}
// 计算总数sql
culCount((Connection) invocation.getArgs()[0], m2);
// 取出sql
String sql = (String) m2.getValue("delegate.boundSql.sql");// 取出属性,OGNL写法
sql = sql.trim();
String start = sql.substring(0, 5);
if (!start.equalsIgnoreCase(start))
return invocation.proceed();// 如果没有select 直接跳过
// 取出传进来的参数
BoundSql bsql = (BoundSql) m2.getValue("delegate.boundSql");
Page p = (Page) bsql.getParameterObject();
if (p.getCurrentPage() == null || p.getPageSize() == null)
// 重新拼接sql
sql = sql + " limit " + (page.getCurrentPage() - 1) * page.getPageSize() + "," + page.getPageSize();
else
sql = sql + " limit " + (p.getCurrentPage() - 1) * p.getPageSize() + "," + p.getPageSize();
p.setPageCount(page.getPageCount());
// 放置在boundsql里
m2.setValue("delegate.boundSql.sql", sql);
PreparedStatement preparedStatement = (PreparedStatement) invocation.proceed();
// 根据接口可以得知最后肯定返回的是一个Statement对象
return preparedStatement;
}
private void culCount(Connection connection, MetaObject m2) {
// 如果要执行一次查询 需要Connection Statement ResultSet
String sql = (String) m2.getValue("delegate.boundSql.sql");
sql = "select count(*) from (" + sql + ") $_paging";
try {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet resultSet = preparedStatement.executeQuery();
int count = 0;
if (resultSet.next()) {
count = resultSet.getInt(1);
}
page.setPageCount(count);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public Object plugin(Object target) {
// TODO Auto-generated method stub
if (target instanceof StatementHandler)
return Plugin.wrap(target, this);// 返回代理对象
return target;
}
@Override
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
int currentPage = Integer.parseInt(properties.getProperty("currentPage"));
int pageSize = Integer.parseInt(properties.getProperty("pageSize"));
page = new Page();
page.setPageSize(pageSize);
page.setCurrentPage(currentPage);
}
}
<plugins>
<plugin interceptor="Mapper.pageInterceptor">
<property name="currentPage" value="1"/>
<property name="pageSize" value="5"/>
</plugin>
</plugins>