`
longgangbai
  • 浏览: 7339394 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

各种数据库分页Dialect的方法

 
阅读更多
以下分页技术均来自hibernate-core-3.3.1.GA-sources中的数据库方言总(Dialect)中。
H2:
    
	public String getLimitString(String sql, boolean hasOffset) {
        return new StringBuffer(sql.length() + 20).
            append(sql).
            append(hasOffset ? " limit ? offset ?" : " limit ?").
            toString();
    }
HSQL:
	public String getLimitString(String sql, boolean hasOffset) {
		return new StringBuffer( sql.length() + 10 )
				.append( sql )
				.insert( sql.toLowerCase().indexOf( "select" ) + 6, hasOffset ? " limit ? ?" : " top ?" )
				.toString();
	}
	
	
DB2:
/**
	 * Render the <tt>rownumber() over ( .... ) as rownumber_,</tt> 
	 * bit, that goes in the select list
	 */
	private String getRowNumber(String sql) {
		StringBuffer rownumber = new StringBuffer(50)
			.append("rownumber() over(");

		int orderByIndex = sql.toLowerCase().indexOf("order by");

		if ( orderByIndex>0 && !hasDistinct(sql) ) {
			rownumber.append( sql.substring(orderByIndex) );
		}

		rownumber.append(") as rownumber_,");

		return rownumber.toString();
	}

	public String getLimitString(String sql, boolean hasOffset) {

		int startOfSelect = sql.toLowerCase().indexOf("select");

		StringBuffer pagingSelect = new StringBuffer( sql.length()+100 )
					.append( sql.substring(0, startOfSelect) ) //add the comment
					.append("select * from ( select ") //nest the main query in an outer select
					.append( getRowNumber(sql) ); //add the rownnumber bit into the outer query select list

		if ( hasDistinct(sql) ) {
			pagingSelect.append(" row_.* from ( ") //add another (inner) nested select
				.append( sql.substring(startOfSelect) ) //add the main query
				.append(" ) as row_"); //close off the inner nested select
		}
		else {
			pagingSelect.append( sql.substring( startOfSelect + 6 ) ); //add the main query
		}

		pagingSelect.append(" ) as temp_ where rownumber_ ");

		//add the restriction to the outer select
		if (hasOffset) {
			pagingSelect.append("between ?+1 and ?");
		}
		else {
			pagingSelect.append("<= ?");
		}

		return pagingSelect.toString();
	}
	
	
MySQL:
	public String getLimitString(String sql, boolean hasOffset) {
		return new StringBuffer( sql.length()+20 )
			.append(sql)
			.append( hasOffset ? " limit ?, ?" : " limit ?")
			.toString();
	}
	
Oracle8i:
	public String getLimitString(String sql, boolean hasOffset) {
		sql = sql.trim();
		boolean isForUpdate = false;
		if ( sql.toLowerCase().endsWith(" for update") ) {
			sql = sql.substring( 0, sql.length()-11 );
			isForUpdate = true;
		}

		StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );
		if (hasOffset) {
			pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
		}
		else {
			pagingSelect.append("select * from ( ");
		}
		pagingSelect.append(sql);
		if (hasOffset) {
			pagingSelect.append(" ) row_ ) where rownum_ <= ? and rownum_ > ?");
		}
		else {
			pagingSelect.append(" ) where rownum <= ?");
		}

		if ( isForUpdate ) {
			pagingSelect.append( " for update" );
		}

		return pagingSelect.toString();
	}
Oracle 9I:
public String getLimitString(String sql, boolean hasOffset) {
		
		sql = sql.trim();
		boolean isForUpdate = false;
		if ( sql.toLowerCase().endsWith(" for update") ) {
			sql = sql.substring( 0, sql.length()-11 );
			isForUpdate = true;
		}
		
		StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );
		if (hasOffset) {
			pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
		}
		else {
			pagingSelect.append("select * from ( ");
		}
		pagingSelect.append(sql);
		if (hasOffset) {
			pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");
		}
		else {
			pagingSelect.append(" ) where rownum <= ?");
		}

		if ( isForUpdate ) {
			pagingSelect.append( " for update" );
		}
		
		return pagingSelect.toString();
	}
	
	
PostgreSQL:
	public String getLimitString(String sql, boolean hasOffset) {
		return new StringBuffer( sql.length()+20 )
			.append(sql)
			.append(hasOffset ? " limit ? offset ?" : " limit ?")
			.toString();
	}

DB2390/DB2400:

	public String getLimitString(String sql, int offset, int limit) {
		return new StringBuffer(sql.length() + 40)
			.append(sql)
			.append(" fetch first ")
			.append(limit)
			.append(" rows only ")
			.toString();
	}

	
Interbase:
	public String getLimitString(String sql, boolean hasOffset) {
		return new StringBuffer( sql.length()+15 )
			.append(sql)
			.append(hasOffset ? " rows ? to ?" : " rows ?")
			.toString();
	}
针对部分数据库没有伪列(rownum,rowid)之类:
在网上MSSQL分页如下:
SQL常用分页的办法~~ 
表中主键必须为标识列,[ID] int IDENTITY (1,1) 
1.分页方案一:(利用Not In和SELECT TOP分页) 
语句形式: 
SELECT TOP 页记录数量 * 
FROM 表名 
WHERE (ID NOT IN 
(SELECT TOP (每页行数*(页数-1)) ID 
FROM 表名 
ORDER BY ID)) 
ORDER BY ID 
//自己还可以加上一些查询条件 
例: 
select top 2 * 
from Sys_Material_Type 
where (MT_ID not in 
(select top (2*(3-1)) MT_ID from Sys_Material_Type order by MT_ID)) 
order by MT_ID 
2.分页方案二:(利用ID大于多少和SELECT TOP分页) 
语句形式: 
SELECT TOP 每页记录数量 * 
FROM 表名 
WHERE (ID > 
(SELECT MAX(id) 
FROM (SELECT TOP 每页行数*页数 id FROM 表 
ORDER BY id) AS T) 
) 
ORDER BY ID 
例: 
SELECT TOP 2 * 
FROM Sys_Material_Type 
WHERE (MT_ID > 
(SELECT MAX(MT_ID) 
FROM (SELECT TOP (2*(3-1)) MT_ID 
FROM Sys_Material_Type 
ORDER BY MT_ID) AS T)) 
ORDER BY MT_ID 
3.分页方案三:(利用SQL的游标存储过程分页) 
create procedure SqlPager 
@sqlstr nvarchar(4000), --查询字符串 
@currentpage int, --第N页 
@pagesize int --每页行数 
as 
set nocount on 
declare @P1 int, --P1是游标的id 
@rowcount int 
exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1, @rowcount=@rowcount output 
select ceiling(1.0*@rowcount/@pagesize) as 总页数--,@rowcount as 总行数,@currentpage as 当前页 
set @currentpage=(@currentpage-1)*@pagesize+1 
exec sp_cursorfetch @P1,16,@currentpage,@pagesize 
exec sp_cursorclose @P1 
set nocount off 
4.总结: 
其它的方案:如果没有主键,可以用临时表,也可以用方案三做,但是效率会低。 
建议优化的时候,加上主键和索引,查询效率会提高。 
通过SQL 查询分析器,显示比较:我的结论是: 
分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高,需要拼接SQL语句 
分页方案一:(利用Not In和SELECT TOP分页) 效率次之,需要拼接SQL语句 
分页方案三:(利用SQL的游标存储过程分页) 效率最差,但是最为通用。

 

分享到:
评论

相关推荐

    PageHelper分页插件Java

    2. **配置MyBatis**:在mybatis-config.xml中配置PageHelper的相关参数,如dialect(数据库类型)、reasonable(是否启用合理化处理)等。 3. **创建Page对象**:在Service或DAO方法中,创建Page对象并传入查询参数...

    mybatis物理分页插件-GbatisDialect

    &lt;?xml version="1.0" encoding="UTF-8" ?&gt; &lt;!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD ... &lt;plugin interceptor="com.gian.commons.dialect.PaginationInterceptor" /&gt; &lt;/configuration&gt;

    mybatis-sql-dialect

    通过使用SQL方言包,MyBatis能够更好地适应各种数据库,如MySQL、Oracle和DB2,使得在切换数据库时无需对SQL语句进行大量修改。 1. **MyBatis框架概述** MyBatis是一个轻量级的ORM(对象关系映射)框架,它消除了...

    pring_mybatis物理分页

    在IT行业中,数据库分页是常见的数据检索方法,特别是在处理大量数据时,为了提高用户体验和系统性能,物理分页显得尤为重要。"Spring_MyBatis物理分页"是指在Spring和MyBatis集成环境中实现的数据库物理分页功能。...

    hibernate连接各种数据库的配置

    ### Hibernate连接各种数据库的配置详解 #### 一、概述 在软件开发中,数据库操作是一项基本且重要的功能。Hibernate作为一种流行的Java持久层框架,能够帮助开发者简化与数据库交互的过程。本文将详细介绍如何...

    SpringBoot+Mybatis+Druid+PageHelper实现多数据源并分页方法

    在实际使用时,我们可以通过PageHelper的startPage()方法开始分页,然后在Mapper接口的查询方法中返回Page对象,Page对象包含了当前页数据以及分页信息。 在实际开发中,为了实现多数据源的切换,我们可以使用...

    Mybatis分页插件PageHelper的JAR包

    Mybatis分页插件PageHelper是Java开发中广泛使用的数据库分页工具,它与Mybatis框架无缝集成,极大地简化了在大数据量查询时的分页处理。PageHelper提供了高效的分页功能,支持多种数据库,包括MySQL、Oracle、SQL ...

    mybatis 分页拦截器及拦截器配置

    2. **配置初始化**:在MyBatis的配置文件中,需要配置PageHelper的初始化参数,如dialect(数据库类型)、reasonable(是否开启合理化参数处理)等。 ```xml ``` 3. **Mapper接口增强**:无需修改原有的...

    spring+mybatis实现了物理分页

    在项目的pom.xml中引入PageHelper依赖,然后在MyBatis的配置文件中启用插件,并设置相关属性,如dialect(数据库类型)。 4. **Spring整合**:在Spring的配置文件中,配置Mapper扫描器,使Spring能够自动扫描并管理...

    mybatis官方分页插件pagehelper 5.1.8

    这款插件由Mybatis官方推出,旨在简化Java开发者的数据库分页查询工作,提高代码的可读性和维护性,同时保持高性能。 首先,PageHelper插件的核心功能是提供强大的分页支持。在传统的Mybatis中,实现分页查询通常...

    如何使用分页插件.pdf

    - dialect:该参数指定了分页插件应使用的方言,默认情况下,分页插件会自动检测数据库并选择合适的分页方法。如果你需要使用特定的分页逻辑,可以通过指定dialect参数的值来选择不同的方言。例如,对于MySQL数据库...

    Hibernate分页查询原理解读

    通过这种方法,可以有效地实现在Oracle数据库中的分页查询。 #### 四、Scrollable Result Set与分页 除了通过SQL语句实现分页外,Hibernate还支持通过`Scrollable ResultSet`来实现分页查询。这种方式主要用于不...

    SSM框架分页的实现

    首先需要在项目的pom.xml文件中添加PageHelper依赖,然后在MyBatis的配置文件中启用插件,并设置相关属性如dialect(数据库类型)、reasonable(是否启用合理化)等。 2. **Service层实现**: 在Service层,我们...

    ssm的mysql分页查询

    - 配置PageHelper的相关属性,如数据库类型、合理设置dialect属性等。 - 初始化PageHelper,一般在Spring的配置文件中添加初始化Bean。 2. **编写Mapper接口和XML文件** - 在Mapper接口中定义一个返回List类型的...

    SSH实现分页

    此外,还需定义dialect属性,确保使用正确的数据库方言。 2. **实体类与映射文件**:为每个数据库表创建对应的实体类,并通过.hbm.xml文件定义实体与数据库表的映射关系。 3. **分页查询**:在业务逻辑层,使用...

    Hibernate中的query 分页.doc

    总结来说,虽然`query.scroll()`提供了更灵活的遍历结果集的方式,但在大多数情况下,使用`query.setFirstResult(), query.setMaxResults()`进行数据库层面的分页是首选,因为这种方法对内存的使用更友好,效率也更...

    Hibernate分页

    总之,Hibernate 的分页机制通过灵活地运用 `Dialect` 类以及针对不同数据库特性的 SQL 语法,大大简化了跨数据库环境下的分页实现过程。这对于需要处理大量数据的应用程序来说,无疑是一个非常有价值的特性。

    hibernate的分页查询

    对于支持分页SQL语句的数据库,如MySQL,其方言类(如`MySQLDialect`)会提供`getLimitString`方法,用于在原SQL后面添加分页逻辑。例如,MySQL使用`LIMIT`关键字来实现分页: ```java public String ...

Global site tag (gtag.js) - Google Analytics