/**
* 模糊查询(分页)
*
* @project apqp
* @author liud JIRA:APQP-23
* @date 2013-04-16
* @param flow
* @param page
* 分页参数包装器
* @return pageData<Flow> 分页结果集
* @history
*/
@Override
public PageData<Attach> queryFlow(Attach attach, Pagination page) {
if (page.isReadTotal())
page.setTotal(this.selectOneByTotalCount("flow.queryList", attach));
RowBounds rowbounds = new RowBounds(page.getStart(), page.getLimit());
List<Attach> result = this.sqlSession.selectList("flow.queryList",
attach, rowbounds);
PageData<Attach> pageData = new PageData<Attach>();
pageData.setResult(result);
pageData.setPagination(page);
return pageData;
}
/**
* 获得分页的总条数
*
* @author liud
* @date 2013-2-18
* @param s
* mybatis对应的命名空间
* @param obj
* 参数
* @return
*/
protected int selectOneByTotalCount(String s, Object obj) {
final BaseEntity baseEntity = new BaseEntity();
RowBounds rowbounds = new RowBounds(-1, -1);
this.sqlSession.select(s, obj, rowbounds, new ResultHandler() {
@Override
public void handleResult(ResultContext context) {
Object object = context.getResultObject();
if (object != null) {
BaseEntity base = (BaseEntity) object;
baseEntity.setTotal(base.getTotal());
}
}
});
return baseEntity.getTotal();
}
-- mybatis.xml flow.queryList
<select id="queryList" resultType="com.eman.flow.entity.Attach"
parameterType="com.eman.flow.entity.Attach">
SELECT f1.fileID
, f1.fileName
, f1.fileType
, f1.fileSize
, f1.uploadUser
, f1.uploadTime
, f2.userName uploadUserName
FROM
t_attachmentOfAPQPFlowPhase p INNER
JOIN t_attachment f1
ON p.fileID =
f1.fileID
INNER JOIN t_user f2 ON f1.uploadUser =
f2.userID
WHERE
p.phaseID = #{phaseID}
order by f1.uploadTime desc
</select>
-- mybatis.config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="sysconfig.properties" />
<plugins>
<plugin interceptor="com.eman.core.interceptor.PaginationInterceptor" />
</plugins>
</configuration>
package com.eman.core.interceptor;
import java.sql.Connection;
import java.util.Properties;
import org.apache.ibatis.executor.statement.StatementHandler;
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.session.Configuration;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.eman.core.dialect.Dialect;
import com.eman.core.dialect.SQLServer2005Dialect;
import com.eman.core.dialect.SQLServer2008Dialect;
/**
* 拦截mybatis执行sql,以用于转换分页sql
*
* @author liud
*
*/
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PaginationInterceptor implements Interceptor {
private static final Logger log = LoggerFactory.getLogger("controller");
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler sh = (StatementHandler) invocation.getTarget();
MetaObject mo = MetaObject.forObject(sh);
RowBounds rb = (RowBounds) mo.getValue("delegate.rowBounds");
if (rb == RowBounds.DEFAULT
|| (rb.getLimit() <= 0 && rb.getLimit() != -1)
|| rb.getLimit() > RowBounds.NO_ROW_LIMIT)
return invocation.proceed();
Configuration conf = (Configuration) mo
.getValue("delegate.configuration");
Dialect dialect = this.invokeDialect(conf.getVariables()
.getProperty("jdbc.db.type").toUpperCase());
if (dialect == null)
return invocation.proceed();
String bSql = (String) mo.getValue("delegate.boundSql.sql");
if (rb.getLimit() == -1 && rb.getOffset() == -1)
bSql = dialect.getTotalString(bSql);
else
bSql = dialect.getLimitString(bSql, rb.getOffset(), rb.getLimit());
mo.setValue("delegate.boundSql.sql", bSql);
mo.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
mo.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
/**
* 通过配置获得sql数据库对象
*
* @author liud
* @date 2013-2-18
* @param param
* @return
*/
private Dialect invokeDialect(String param) {
Dialect.Type type = null;
try {
type = Dialect.Type.valueOf(param);
} catch (Exception e) {
log.debug(
"the value of the dialect property in mybatis-config.xml is not defined:{}",
param);
}
Dialect dialect = null;
switch (type) {
case SQLSERVER:
break;
case SQLSERVER2005:
dialect = new SQLServer2005Dialect();
break;
case SQLSERVER2008:
dialect = new SQLServer2008Dialect();
break;
case ORACLE9I:
break;
case ORACLE10G:
break;
case ORACLE11G:
break;
case MYSQL5:
break;
}
return dialect;
}
}
package com.eman.core.dialect;
/**
* sql2008数据库的实现
*
* @author liud
*
*/
public class SQLServer2008Dialect implements Dialect {
private static final String SELECT = "select";
private static final String FROM = "from";
private static final String DISTINCT = "distinct";
@Override
public String getTotalString(String sql) {
StringBuilder sb = new StringBuilder(sql.trim().toLowerCase());
int orderbyIndex = sb.indexOf("order by");
if (orderbyIndex != -1) {
sb.delete(orderbyIndex, sb.length());
}
sb.insert(0, "WITH query AS (").append(
") SELECT count(*) total FROM query ");
return sb.toString();
}
@Override
public String getLimitString(String sql, int offset, int limit) {
if (offset > 1 || limit > 1)
return getLimitString(sql, offset, limit, true);
return sql;
}
/**
* Add a LIMIT clause to the given SQL SELECT (HHH-2655: ROW_NUMBER for
* Paging)
*
* The LIMIT SQL will look like:
*
* <pre>
* WITH query AS (
* SELECT ROW_NUMBER() OVER (ORDER BY orderby) as __liud_row_nr__,
* original_query_without_orderby
* )
* SELECT * FROM query WHERE __liud_row_nr__ BEETWIN offset AND offset + last
* </pre>
*
*
* @param querySqlString
* The SQL statement to base the limit query off of.
* @param offset
* Offset of the first row to be returned by the query
* (zero-based)
* @param limit
* Maximum number of rows to be returned by the query
*
* @return A new SQL statement with the LIMIT clause applied.
*/
private String getLimitString(String querySqlString, int offset, int limit,
boolean hasOffset) {
StringBuilder sb = new StringBuilder(querySqlString.trim()
.toLowerCase());
int orderByIndex = sb.indexOf("order by");
CharSequence orderby = orderByIndex > 0 ? sb.subSequence(orderByIndex,
sb.length()) : "ORDER BY CURRENT_TIMESTAMP";
// Delete the order by clause at the end of the query
if (orderByIndex > 0) {
sb.delete(orderByIndex, orderByIndex + orderby.length());
}
// HHH-5715 bug fix
replaceDistinctWithGroupBy(sb);
insertRowNumberFunction(sb, orderby);
// Wrap the query within a with statement:
sb.insert(0, "WITH query AS (").append(") SELECT * FROM query ");
sb.append("WHERE __liud_row_nr__ BETWEEN ").append(offset + 1)
.append(" AND ").append(offset + limit);
return sb.toString();
}
/**
* Right after the select statement of a given query we must place the
* row_number function
*
* @param sql
* the initial sql query without the order by clause
* @param orderby
* the order by clause of the query
*/
protected static void insertRowNumberFunction(StringBuilder sql,
CharSequence orderby) {
// Find the end of the select statement
int selectEndIndex = sql.indexOf(SELECT) + SELECT.length();
// Insert after the select statement the row_number() function:
sql.insert(selectEndIndex, " ROW_NUMBER() OVER (" + orderby
+ ") as __liud_row_nr__,");
}
/**
* Utility method that checks if the given sql query is a select distinct
* one and if so replaces the distinct select with an equivalent simple
* select with a group by clause. See
* {@link SQLServer2005DialectTestCase#testReplaceDistinctWithGroupBy()}
*
* @param sql
* an sql query
*/
protected static void replaceDistinctWithGroupBy(StringBuilder sql) {
int distinctIndex = sql.indexOf(DISTINCT);
if (distinctIndex > 0) {
sql.delete(distinctIndex, distinctIndex + DISTINCT.length() + 1);
sql.append(" group by").append(getSelectFieldsWithoutAliases(sql));
}
}
/**
* This utility method searches the given sql query for the fields of the
* select statement and returns them without the aliases. See
* {@link SQLServer2005DialectTestCase#testGetSelectFieldsWithoutAliases()}
*
* @param an
* sql query
* @return the fields of the select statement without their alias
*/
protected static CharSequence getSelectFieldsWithoutAliases(
StringBuilder sql) {
String select = sql.substring(sql.indexOf(SELECT) + SELECT.length(),
sql.indexOf(FROM));
// Strip the as clauses
return stripAliases(select);
}
/**
* Utility method that strips the aliases. See
* {@link SQLServer2005DialectTestCase#testStripAliases()}
*
* @param a
* string to replace the as statements
* @return a string without the as statements
*/
protected static String stripAliases(String str) {
return str.replaceAll("\\sas[^,]+(,?)", "$1");
}
}
以上是集成了mybatis的分页功能,只需要调用第一方法即可以实现。实现方式采用了hibernate分页方式。
2013年6月09日 14:57
相关推荐
本实例将详细介绍如何在MyBatis中实现MySQL的分页查询,帮助开发者提高应用性能,提升用户浏览数据的体验。 首先,我们要理解分页的基本概念。分页是将大量数据分成多个小部分,每次只加载一部分到内存中,这样可以...
但是,在参考写的同时也发现有很多地方都不解不能直接用的问题,导致实际使用的过程中经常会出错,参考原来做的项目,以及网上的资料,整理了一个比较简单的自己理解的spring+spring mvc+mybatis+mysql实现的分页的...
mybatis 分页 mybatis-generate Mysql数据库 大家知道mybatis自动生成代码是没有分页功能的 我在网上找了很久 有很多内容 但正真可以使用的少之又少 本人整合了网上的资源 整理了基于Mysql数据库的mybatis插件 经...
在SpringBoot项目中,整合Mybatis-Plus并实现多数据源的动态切换,同时支持分页查询是一项常见的需求。以下将详细阐述这个过程中的关键步骤和技术要点。 首先,我们需要引入必要的Maven依赖。这里提到了四个关键...
在本案例中,我们主要探讨如何使用Ajax、JSON、MyBatis和MySQL来实现一个类似于百度的简单分页功能。这个教程特别适合那些希望提升自己技能的程序员,通过阅读源代码和注释,你可以深入理解这些技术的结合使用。下面...
MyBatis的分页插件主要有PageHelper和MyBatis-Plus两种常见的实现方式。 1. **PageHelper插件**:PageHelper是基于MyBatis的分页插件,它可以自动进行结果集的分页处理。其核心功能包括: - **智能分页**:根据...
mybatis支持MYSQL分页 暂只支持MYSQL且不适用与MYBATIS-SPRING一起使用 调用方法 List selectList(String statement, int start ,int end) 与 List selectList(String statement, Object parameter, int start ,int ...
总的来说,实现Spring MVC、MyBatis和MySQL的分页功能,主要涉及后端分页逻辑的实现和前端的交互。理解分页的基本原理和组件之间的协作,能够帮助开发者高效地构建出符合需求的分页功能。在实际开发中,还可以结合...
在本项目中,我们主要探讨如何在SpringMVC和Mybatis框架中实现分页功能,同时结合RESTful API设计原则来构建一个高效、易用的Web应用。分页是大型Web应用不可或缺的一部分,它能够有效地管理和展示大量数据,提高...
MyBatis的分页机制主要依赖于SQL语句的构造,通过在动态SQL中添加LIMIT和OFFSET关键字来实现。例如,在MySQL数据库中,分页查询的基本形式为: ```sql SELECT * FROM table LIMIT offset, limit; ``` 这里的`...
基于Springboot+MyBatis+MySQL实现多功能个人博客系统 项目经过严格测试,确保可以运行! 功能点: 用户注册登录功能 Markdown文章发布功能 文章分页显示 文章分类 文章标签/标签云 文章点击量 阅读排行 赞...
在本文中,我们将深入探讨如何使用JSP、Servlet和MyBatis这三种技术来实现一个分页查询的功能。这是一个常见的需求,在许多Web应用程序中,为了提高用户体验,通常需要将大量数据分批次展示,而不是一次性加载所有...
总结,MyBatis中的分页实现主要是通过应用层的逻辑和动态SQL来完成。尽管基于内存的分页方法在小型项目中足够用,但对于大型项目,推荐使用数据库原生的分页功能以提高性能。在实际开发中,应根据项目需求和数据规模...
5. **分页查询**:在MyBatis中实现分页查询,你可以使用`<foreach>`标签配合LIMIT和OFFSET子句,或者使用MyBatis的PageHelper插件,它提供更方便的分页API。 6. **事务管理**:MyBatis的事务管理可以手动或自动进行...
在这个项目中,开发者使用了这些框架以及MySQL数据库来实现分页功能,借助PageHelper插件。下面将详细阐述这个项目中的核心技术和知识点。 1. **Spring框架**:Spring作为基础容器,负责管理应用对象(如Service、...
在本文中,我们将深入探讨如何使用Spring MVC和MyBatis框架来实现MySQL数据库的分页数据查询。首先,我们需要理解分页在Web开发中的重要性,尤其是在处理大量数据时,它可以提高应用程序的性能并提供更好的用户体验...
总结,MyBatis通过动态SQL和参数传递实现了最简单的分页查询,而分页的实现原理主要是通过SQL的`LIMIT`子句。在实际应用中,结合最佳实践和第三方插件,可以进一步提升分页功能的效率和灵活性。同时,针对不同的场景...
Mybatis分页拦截器的核心工作原理是:在执行SQL查询时,拦截SQL语句,动态添加分页相关的SQL片段,如LIMIT或OFFSET等,然后执行改写后的SQL,从而实现分页效果。这种方式的好处在于保持了SQL的简洁性和可读性,同时...
总结起来,本文介绍了如何利用Mybatis的动态SQL功能实现MySQL的物理分页,这种方法对于处理大数据量的查询非常有效,可以防止内存溢出并提高应用的性能。在实际开发中,理解和掌握这一技巧对于优化数据库操作和提升...
本篇将聚焦于MyBatis的代码自动生成和分页功能,特别是在MySQL数据库中的应用。 一、MyBatis代码生成器(MyBatis Generator) MyBatis Generator(MBG)是MyBatis官方提供的一个工具,可以自动生成Java模型类、...