`

使用Hibernate查询DB2时Query接口setFetchSize方法的正确使用方式

 
阅读更多

公司有个项目,采用DB2数据库,持久化技术为Hibernate。

近期有个同事发现Hibernate生成的分页SQL语句查询速度很慢,凭经验,他在该sql语句后面加上了

fetch first 10 rows only

查询速度一下子提高上去了,因此他在Hibernate中的Query调用中增加了.setFetchSize(10)。但是发现Hibernate解析出来的sql并没有增加上面的fetch子句。

其实这个问题的原因在于Hibernate的Dialect不正确,一般的,我们会选择org.hibernate.dialect.DB2Dialect,但其实应该选择org.hibernate.dialect.DB2400Dialect,该类源代码(部分):

	public String getLimitString(String sql, int offset, int limit) {
		if ( offset > 0 ) {
			throw new UnsupportedOperationException( "query result offset is not supported" );
		}
		return new StringBuffer( sql.length() + 40 )
				.append( sql )
				.append( " fetch first " )
				.append( limit )
				.append( " rows only " )
				.toString();
	}

注意到,DB2400Dialect类是继承于DB2Dialect类的。

这样改后, Hibernate解析出来的sql语句就顺利地加上fetch子句了。

 

另记录一下搭建测试代码时碰到的一些问题:

1. DB2的JDBC驱动:我在MAC上使用DbVisualizer-8.0.9,该工具自带了DB2的一个驱动包,放置于/Applications/DbVisualizer-8.0.9.app/Contents/Resources/app/jdbc/db2/db2jcc.jar,手工install到本地Maven仓库

$mvn install:install-file -Dfile=db2jcc.jar -DgroupId=com.ibm.db2.jcc -DartifactId=db2jcc -Dversion=8 -Dpackaging=jar

 

2. Hibernate版本: 搭建测试代码时,首先使用的是Hibernate4,pom文件(部分):

  	<dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-core</artifactId>
  		<version>4.1.2.Final</version>
  		<!-- 
  		<exclusions>
  			<exclusion>
  				<groupId>org.jboss.logging</groupId>
  				<artifactId>jboss-logging</artifactId>
  			</exclusion>
  		</exclusions>
  		 -->
  	</dependency>

运行测试代码时报错:

DEBUG: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Could not open connection [n/a]
java.sql.SQLException: No suitable driver found for jdbc:db2://(略去)
	at java.sql.DriverManager.getConnection(DriverManager.java:602)
	at java.sql.DriverManager.getConnection(DriverManager.java:154)

死活不知道原因,后来将Hibernate版本降至3.6.0.Final,顺利通过测试,相关pom文件

  <dependencies>
  	<dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-core</artifactId>
  		<version>3.6.0.Final</version>
  		<!-- 
  		<exclusions>
  			<exclusion>
  				<groupId>org.jboss.logging</groupId>
  				<artifactId>jboss-logging</artifactId>
  			</exclusion>
  		</exclusions>
  		 -->
  	</dependency>
  	<dependency>
  		<groupId>javassist</groupId>
  		<artifactId>javassist</artifactId>
  		<version>3.12.1.GA</version>
  	</dependency>
  	<dependency>
  		<groupId>org.slf4j</groupId>
  		<artifactId>slf4j-log4j12</artifactId>
  		<version>1.6.1</version>
  	</dependency>
  	<dependency>
  		<groupId>log4j</groupId>
  		<artifactId>log4j</artifactId>
  		<version>1.2.16</version>
  	</dependency>
  	<dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.8.2</version>
   </dependency>
   <!-- 
   <dependency>
       <groupId>com.h2database</groupId>
       <artifactId>h2</artifactId>
       <version>1.2.145</version>
   </dependency>
    -->
   <dependency>
	   <groupId>com.ibm.db2.jcc</groupId>
	   <artifactId>db2jcc</artifactId>
	   <version>8</version>
  </dependency> 
   
  </dependencies>

唔,从这方面以及控制台输入的日志内容看Hibernate4对比Hibernate3的改动是非常大的。

至于为什么Hibernate4报错,留给未来*有时间*再研究吧。

 

参考链接:

What is difference between setMaxResults and setFetchSize in org.hibernate.Query?

Can not get N first results of query with DB2 dialect (neither with setMaxResults nor with setFetchSize)

分享到:
评论

相关推荐

    Hibernate Tutorial 09 Hibernate Query Language

    Hibernate Query Language(简称 HQL)是 Hibernate 提供的一种强大的查询语言,其设计目标是为了提供一种更接近于面向对象编程的查询方式。本文将深入探讨 HQL 的基本概念、语法以及一些高级用法,帮助读者更好地...

    Hibernate缓存机制

    - 在调用`flush()`方法时,会将Session内的状态同步到数据库,并且也会清空缓存。 **2.2 JDBC与Hibernate的区别** - 直接使用JDBC操作数据库时,如果不主动清理缓存,数据库的变化不会立即反映出来。 - Hibernate...

    hibernate-biji

    Hibernate的批处理功能可以提高性能,例如,通过`Session.saveOrUpdateAll()`方法批量保存实体,或使用`Query.setFetchSize()`设置查询结果集大小。 以上就是“hibernate-biji”中涉及的一些关键知识点。通过学习...

    day36 08-Hibernate抓取策略:批量抓取

    默认情况下,Hibernate使用懒加载机制,即当需要关联对象时才去数据库加载,这可能导致大量的单独数据库查询,降低性能。为了解决这个问题,Hibernate提供了几种抓取策略,包括批量抓取和预加载。 批量抓取允许我们...

    hibernate经典分页源代码

    使用 HQL 查询时,分页可以通过在查询语句中添加 `LIMIT` 和 `OFFSET` 子句来实现,但不是所有数据库都支持这种方式。在 Hibernate 中,可以使用 `scroll()` 方法结合 ScrollableResults 来实现分页: ```java ...

    Hibernate学习资料

    - **批处理**:使用BatchSize属性或setFetchSize()方法实现批量插入、更新和查询,减少数据库交互次数。 - **懒加载与立即加载**:根据需求选择何时加载关联对象,减少内存占用。 - **缓存策略**:合理配置缓存,...

    Hibernate 参数配置详解

    - **描述**:用于指定 Hibernate 针对特定关系数据库生成 SQL 语句时使用的方言。不同的数据库可能有不同的 SQL 语法和特性支持,因此正确配置方言至关重要。 - **取值**:应设置为数据库对应的 `org.hibernate....

    让hibernate输出sql语句参数配置.doc

    下面将详细介绍 Hibernate 配置参数的用途和使用方法。 1. hibernate.dialect hibernate.dialect 是一个 Hibernate Dialect 类名,允许 Hibernate 针对特定的关系数据库生成优化的 SQL。其取值为 full.classname....

    hibernate参数配置

    15. **hibernate.jdbc.batch_versioned_data**: 开启后,Hibernate会在自动版本化的数据上使用批量DML,返回正确的行计数。 16. **hibernate.jdbc.factory_class**: 可以选择自定义的`Batcher`实现,但大多数情况下...

    hibernate中实现真分页和假分页技术

    然而,Hibernate原生并不直接支持这些特性,我们需要自定义SQL查询或者使用`ScrollableResults`接口来实现。 #### 使用自定义SQL查询 在实体类上添加`@NamedNativeQuery`注解,定义SQL查询,例如: ```java @...

    达内培训hibernate电子教案

    1. 批量操作:使用Session的batch_size属性,或者通过Criteria的setFetchSize()方法批量获取数据。 2. 分页查询:避免一次性加载大量数据,使用Criteria的setFirstResult()和setMaxResults()进行分页。 3.延迟加载:...

    com.microsoft.sqlserver.jdbc.SQLServerException: 只进结果集不支持请求的操作 解决方案

    Hibernate提供了多种方式来实现分页,其中一种常见方法是通过`Session`对象的`createCriteria()`方法创建查询标准,然后调用`setFirstResult()`和`setMaxResults()`来限制结果集的范围。然而,在某些情况下,这种...

    Hibernate可选配置大全

    - **取值**:整数,通过`Statement.setFetchSize()`方法生效。 ##### 2. hibernate.jdbc.batch_size - **功能**:控制批量更新的规模。 - **取值**:推荐范围`5`至`30`。 ##### 3. hibernate.jdbc.batch_...

    jdbcTemplate分页彻底解决,使用游标滚动

    在处理大量数据时,传统的分页方式可能会导致内存溢出,这时可以使用游标滚动来实现高效的分页。本篇文章将深入探讨如何利用JdbcTemplate结合游标滚动来解决分页问题。 首先,我们要理解什么是游标滚动。在数据库中...

    Hibernate性能优化共9页.pdf.zip

    - 使用`HQL`(Hibernate Query Language)或`Criteria API`代替`SQL`,让Hibernate更好地利用其内部优化机制。 - 避免在`HAVING`子句中使用集合函数,这可能导致全表扫描。 - 限制结果集大小,使用`FirstResult`...

    java一次性查询处理几百万数据解决方法

    ### Java一次性查询处理几百万数据解决方法 在Java开发中,处理大数据量是常见的需求之一,特别是当数据规模达到几百万级别时,如何高效、稳定地处理这些数据变得尤为重要。本文将详细介绍一种Java一次性查询处理几...

    java分页

    2. **JDBC分页**:使用Java Database Connectivity (JDBC) 直接操作数据库时,可以通过设置`Statement`或`PreparedStatement`的`setFetchSize()`方法来控制每次获取的结果数量,但这种方式并不提供真正的分页,只是...

    Java ResultSet导出大数据.docx

    在从数据库读取数据时,分页查询是一种常见方法,但随着页数增加,查询速度会变慢。为了提高效率,可以尝试获取一个游标,然后按批次读取和写入数据。Java的PreparedStatement接口允许我们设置游标类型和获取结果集...

    JDBC连接优化

    参数名称 外部配置建议值 上限 下限 默认值 描述各指标设计

    java Pagination(分页并操作)

    `Criteria`中使用`setFirstResult()`和`setMaxResults()`,`Query`中使用`setFirstResult()`和`setMaxResults()`或`setFetchSize()`。例如: ```java Criteria criteria = session.createCriteria(YourEntity....

Global site tag (gtag.js) - Google Analytics