`

Mybatis3.0.6 结合hibernate3.6.8 Dialect 进行物理物理分页

 
阅读更多

mybatis插件配置:

 

	<plugins>
		<plugin interceptor="com.xuanwu.sms.smstask.webmanager.common.crud.plugins.PaginationInterceptor">
			<property name="dialectClass" value="org.hibernate.dialect.SQLServer2005Dialect"/>
		</plugin>
	</plugins>

 

 

插件处理类:

package com.xuanwu.sms.smstask.webmanager.common.crud.plugins;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

import org.apache.ibatis.builder.SqlSourceBuilder;
import org.apache.ibatis.builder.xml.dynamic.DynamicContext;
import org.apache.ibatis.builder.xml.dynamic.SqlNode;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.parameter.DefaultParameterHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
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.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.hibernate.dialect.Dialect;

import com.xuanwu.sms.smstask.webmanager.common.crud.entity.IPage;
import com.xuanwu.sms.smstask.webmanager.common.crud.entity.Pagination;

@Intercepts( { @Signature(type = Executor.class, method = "query", args = {
		MappedStatement.class, Object.class, RowBounds.class,
		ResultHandler.class }) })
public class PaginationInterceptor implements Interceptor {

	Dialect dialect;
	
	public Object intercept(Invocation invocation) throws Throwable {

		Object parameterObject = invocation.getArgs()[1];
		
		if(parameterObject != null && parameterObject instanceof IPage){
			IPage page =(IPage)parameterObject;
			if (page.getPagination() == null|| page.getPagination().isAvailable()) {
				return pageIntercept(invocation);
			}
		}
		return invocation.proceed();
	}
	
	
	
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	public void setProperties(Properties properties) {
		String dialectClass = properties.getProperty("dialectClass");
		try {
			 dialect = (Dialect) Class.forName(dialectClass).newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	private Object pageIntercept(Invocation invocation) throws Throwable{
		int rowCount = 0;
		MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
		Object parameterObject = invocation.getArgs()[1];
		SqlSource sqlSource = getCountSqlSource(mappedStatement, parameterObject);
		MappedStatement newMappedStatement = copyMappedStatementBySqlSource(mappedStatement, sqlSource);
		Connection connection = newMappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection();
		DefaultParameterHandler dp = new DefaultParameterHandler(mappedStatement,parameterObject,sqlSource.getBoundSql(parameterObject));
		PreparedStatement countStmt = connection.prepareStatement(sqlSource.getBoundSql(parameterObject).getSql());    
		dp.setParameters(countStmt);
		ResultSet rs= countStmt.executeQuery();
		if(rs.next()){
			rowCount =rs.getInt(1);
		}
		rs.close();    
		countStmt.close();
		connection.close();
		
		IPage page =(IPage)parameterObject;
		
		if (page.getPagination() == null) {
			page.setPagination(new Pagination());
		}
		
		page.getPagination().setRowCount(rowCount);
		page.getPagination().pagination();
		sqlSource = getPageLimitSqlSource(mappedStatement, parameterObject);
		newMappedStatement = copyMappedStatementBySqlSource(mappedStatement, sqlSource);
		invocation.getArgs()[0] = newMappedStatement;
		return invocation.proceed();
	}
	

	private String getMapperSQL(MappedStatement mappedStatement,Object parameterObject) throws Throwable{
		SqlSource nowSqlSource = mappedStatement.getSqlSource();
		Class<?> sqlSourceType = nowSqlSource == null ? Object.class : nowSqlSource.getClass();
		Field rootSqlNodeField = sqlSourceType.getDeclaredField("rootSqlNode");
		rootSqlNodeField.setAccessible(true);
		SqlNode sqlNode = (SqlNode) rootSqlNodeField.get(nowSqlSource);
		DynamicContext context = new DynamicContext(mappedStatement.getConfiguration(), parameterObject);
		sqlNode.apply(context);
		return context.getSql();
	}
	
	private SqlSource getCountSqlSource(MappedStatement mappedStatement,Object parameterObject) throws Throwable{
		SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(mappedStatement.getConfiguration());
		String mapperSQL = getMapperSQL(mappedStatement,parameterObject);
		Class<?> parameterType = parameterObject == null ? Object.class: parameterObject.getClass();
		String newSql = "select count(1) from ( "+ mapperSQL+" ) t";
		SqlSource sqlSource = sqlSourceParser.parse(newSql, parameterType);
		return sqlSource;
	}
	
	private SqlSource getPageLimitSqlSource(MappedStatement mappedStatement,Object parameterObject) throws Throwable {
		SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(mappedStatement.getConfiguration());
		String mapperSQL = getMapperSQL(mappedStatement,parameterObject);
		Class<?> parameterType = parameterObject == null ? Object.class: parameterObject.getClass();
		IPage page =(IPage)parameterObject;
		String newSql = getLimitString(mapperSQL, page.getPagination().getCurrentMinRow(), page.getPagination().getCurrentMaxRow());
		SqlSource sqlSource = sqlSourceParser.parse(newSql, parameterType);
		return sqlSource;
	}
	
	private MappedStatement copyMappedStatementBySqlSource(MappedStatement mappedStatement,SqlSource sqlSource){
		MappedStatement.Builder builder = new MappedStatement.Builder(mappedStatement.getConfiguration(), mappedStatement.getId(),sqlSource, mappedStatement.getSqlCommandType());
		builder.resource(mappedStatement.getResource());     
		builder.fetchSize(mappedStatement.getFetchSize());     
		builder.statementType(mappedStatement.getStatementType());     
		builder.keyGenerator(mappedStatement.getKeyGenerator());     
		builder.keyProperty(mappedStatement.getKeyProperty());     
		builder.timeout(mappedStatement.getTimeout());     
		builder.parameterMap(mappedStatement.getParameterMap());     
		builder.resultMaps(mappedStatement.getResultMaps());     
		builder.cache(mappedStatement.getCache());     
		MappedStatement newMappedStatement = builder.build();
		return newMappedStatement;
	}
	
	private String getLimitString(String sql, int offset, int limit) {
		
		String whereLowerCase = null;
		String finalSql = null;
		String sqlLowerCase = sql.trim().toLowerCase();
	
		int whereIndex = sqlLowerCase.indexOf("where");
		if (whereIndex > 0) {
			whereLowerCase = sqlLowerCase.substring(whereIndex);
		}
		
		String limitArgs[] = new String[] { String.valueOf(offset),String.valueOf(limit)};
		String newSql = dialect.getLimitString(sqlLowerCase, offset, limit);
		String sqls[] = newSql.split("\\?");
		String querySQL = "";
		for (int i = 0; i < 2; i++) {
			querySQL = querySQL + " " + sqls[i] + limitArgs[i];
		}

		querySQL = querySQL.trim();
		
		if (whereLowerCase == null || "".endsWith(whereLowerCase)) {
			return querySQL;
		}
		
		int finalWhereIndex = querySQL.indexOf(whereLowerCase);

		if (finalWhereIndex > 0) {
			String begin = querySQL.substring(0, finalWhereIndex);
			String end = querySQL.substring(finalWhereIndex + whereLowerCase.length());
			finalSql = begin + sql.substring(whereIndex) + end;
		}
		return finalSql;
		
	}

}

 

分页接口:

package com.xuanwu.sms.smstask.webmanager.common.crud.entity;

import java.io.Serializable;

public interface IPage extends Serializable {
	
	public Pagination getPagination();

	public void setPagination(Pagination pagination);
}

 

分页实体类:

package com.xuanwu.sms.smstask.webmanager.common.crud.entity;

import java.io.Serializable;


public class Pagination implements Serializable{

	private static final long serialVersionUID = -6579435031214235862L;

	private int rowCount;// 总记录数
	private int pageSize = 15;// 每页记录数
	private int pageCount;// 总页数
	private int currentPage;// 当前页数
	private boolean next;// 是否能下一页
	private boolean previous;// 是否能上一页
	private boolean available = true;//是否分页
	
	public Pagination(){
		
	}
	
	public Pagination(String currentPage, int rowCount) {
		if (currentPage == null) {
			this.currentPage = 1;
		} else {
			this.currentPage = Integer.parseInt(currentPage);
		}
		this.rowCount = rowCount;
		// 计算总页数
		this.pageCount = (int) Math.ceil(this.rowCount / (double) this.pageSize);
		// 计算是否能上一页和下一页
		this.next = this.currentPage < this.pageCount;
		this.previous = this.currentPage > 1;
		
		
	}
	
	public Pagination pagination() {
		if (currentPage == 0) {
			this.currentPage = 1;
		}
		// 计算总页数
		this.pageCount = (int) Math
				.ceil(this.rowCount / (double) this.pageSize);
		// 计算是否能上一页和下一页
		this.next = this.currentPage < this.pageCount;
		this.previous = this.currentPage > 1;
		return this;
	} 

	public int getPageCount() {
		return pageCount;
	}

	public int getCurrentPage() {
		return currentPage;
	}

	public int getRowCount() {
		return rowCount;
	}

	public void setRowCount(int rowCount) {
		this.rowCount = rowCount;
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public int getCurrentMinRow() {
		return (currentPage-1) * pageSize;
	}

	public int getCurrentMaxRow() {
		return currentPage * pageSize - 1;
	}

	public int getNextPage() {
		if (next) {
			return currentPage + 1;
		}
		return currentPage;
	}

	public int getPreviousPage() {
		if (previous) {
			return currentPage - 1;
		}
		return currentPage;
	}

	public boolean isNext() {
		return next;
	}

	public boolean isPrevious() {
		return previous;
	}

	public int nextPage() {
		if (next) {
			currentPage = currentPage + 1;
		}
		return currentPage;
	}

	public int previousPage() {
		if (previous) {
			currentPage = currentPage - 1;
		}
		return currentPage;
	}

	public boolean isAvailable() {
		return available;
	}

	public void setAvailable(boolean available) {
		this.available = available;
	}
}

 

pom.xml

 

mybatis版本:

  <dependency>
   <groupId>org.mybatis</groupId>
   <artifactId>mybatis</artifactId>
   <version>3.0.6</version>
   <scope>compile</scope>
  </dependency>

 

hibernate版本

  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>3.6.8.Final</version>
  </dependency>

分享到:
评论
2 楼 cczakai 2012-04-09  
性能调优,对于千万级别的数据表,查询使用mybatis是用性能瓶颈的,因为mybatis本身是逻辑分页,所以效率很慢,使用物理分页就是为了解决这个问题的。
1 楼 hillfallshore 2012-03-25  
这个分页有什么优点?

相关推荐

    Spring3.0.6 +mybatis 3.0.6配置文档

    Spring3.0.6 +mybatis 3.0.6配置文档

    mybatis 3.0.6 源代码

    The mybatis data mapper framework makes it easier to use a relational database with object-oriented applications. mybatis couples objects with stored procedures or SQL statements using a XML ...

    完整mybatis3.0.6与spring3.0整合例子

    MyBatis 3.0.6 是一个流行的Java持久层框架,它简化了与数据库的交互,而Spring 3.0则是一个全面的企业级应用框架,提供了依赖注入、AOP(面向切面编程)、事务管理等功能。将这两个框架整合在一起可以实现更高效、...

    mybatis 3.0.6 all + 中文指导手册

    在3.0.6版本中,MyBatis已经相当成熟,它提供了许多特性,如动态SQL、映射文件和注解的结合,以及对复杂查询的支持。 中文指导手册是开发者掌握MyBatis的关键资源,尤其对于中文用户来说,阅读本土化的文档可以更...

    mybatis-3.0.6-官方资料

    10. **Mapper API**:除了 XML 配置,MyBatis 3.0.6 还引入了基于注解的 Mapper API,可以直接在接口方法上使用注解来定义 SQL 语句。 11. **MyBatis-Spring 集成**:如果项目使用了 Spring,可以集成 MyBatis-...

    mybatis-3.0.6.jar.zip

    安全,可以对其进行数字签名,只让能够识别数字签名的用户使用里面的东西。 加快下载速度; 压缩,使文件变小,与ZIP压缩机制完全相同。 包封装。能够让JAR包里面的文件依赖于统一版本的类文件。 可移植性,能够...

    mybatis-3.0.6

    《MyBatis-3.0.6:深入解析与应用》 MyBatis,作为一款优秀的持久层框架,因其简洁的API设计和强大的映射能力,深受广大Java开发者喜爱。本资源聚焦于MyBatis的3.0.6版本,通过相关文档,我们可以深入理解MyBatis的...

    mybatis-sql-dialect

    MyBatis-SQL-Dialect是MyBatis框架的一个扩展,主要目的是为了支持不同数据库系统之间的SQL方言差异。MyBatis是一个流行的Java持久层框架,它允许开发者将SQL语句直接集成到XML或Java代码中,提供了灵活的数据访问层...

    Mybatis3.0.6生成器小Demo

    在Mybatis3.0.6版本中,引入了一个强大的工具——生成器(Generator),它能帮助开发者自动生成实体类、Mapper接口以及对应的XML配置文件,大大减少了手动编写这些代码的工作量。 生成器的核心功能是根据数据库表...

    mybatis-3.0.6-javadoc.jar

    mybatis-3.0.6-javadoc.jar

    spring+mybatis实现了物理分页

    本项目是基于Spring和MyBatis框架实现的物理分页,让我们来深入探讨这个主题。 首先,Spring是一个开源的Java应用程序框架,它提供了一种依赖注入(Dependency Injection,DI)的方式来管理对象,使得代码更加模块...

    06实现mybatis分页插件demo

    06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo...

    mybatis-3-mybatis-3.0.6.zip

    3. **注解支持**:除了XML映射,3.0.6版本的MyBatis也支持在Java类和方法上使用注解进行映射。这样可以使代码更简洁,减少XML文件的维护工作。 4. **动态SQL**:MyBatis 提供了强大的动态SQL功能,可以在XML或注解...

    mybatis-3.0.6-SNAPSHOT

    5. **参数映射与结果映射**:MyBatis自动将Java对象的属性与数据库字段进行映射,使得传入参数和返回结果可以无缝对接。映射可以通过注解或XML文件完成。 6. **缓存机制**:MyBatis提供了本地缓存和二级缓存,可以...

    hibernate与mybatis一起使用取长补短

    将Hibernate和MyBatis结合使用,可以实现以下目标: 1. **数据持久化**: 对于常规的CRUD操作和复杂的业务逻辑,可以使用Hibernate,它能够自动处理对象的持久化,简化代码,提高开发效率。 2. **性能优化**: 对于...

    mybatis物理分页插件

    物理分页是指在数据库层面进行分页,相比于逻辑分页(在应用层进行数据截取),物理分页通常更高效,因为它减少了传输到应用程序的数据量,降低了服务器负担。该插件兼容多种主流数据库,如MySQL、Oracle、SQL ...

    ibator_3.0.6.full mybatis 代码生成器插件.zip

    《Mybatis ibator 3.0.6全功能代码生成器插件详解及使用指南》 在Java开发中,Mybatis作为一个轻量级的持久层框架,因其灵活、高效的特性深受开发者喜爱。然而,手动编写SQL映射和实体类等工作会消耗大量时间,这时...

    利用Mybatis3.0.6+DhtmlxGrid做的一个简单的demo

    一个简单的demo,里面有一些关于DhtmlxGrid的操作,注释什么的都有,数据库脚本也有,在src下面有一个sql文件...当然,mybatis的核心包和oracle数据库的驱动包都是有的,所以大家可以直接运行看效果...

    mybatis-3.0.6.jar

    MyBatis是一个强大的Java持久层框架,它最初是Apache组织下的一个开源项目iBatis,于2010年迁移到Google Code并更名为MyBatis。这个框架的主要目的是简化数据库操作,将SQL与Java代码紧密集成,使得开发人员能够更...

Global site tag (gtag.js) - Google Analytics