`

hibernate抓取策略,batch-size的用法

 
阅读更多

hibernate抓取策略,,batch-szie在<class>上的应用

batch-size属性,可以批量加载实体类。

MyClass.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.org.model">
	<class name="MyClass" table="class" batch-size="3">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name" not-null="true"/>
		
		<!-- set标签中的name为MyClass类中多方对应的属性名        key标签中的column为多方数据库表中的外键字段-->
		<set name="students"  cascade="save-update" inverse="true">
			<key column="class_id" not-null="true"></key>
			
			<one-to-many class="Student"/>      <!-- class表明set中放的是什么类型的集合 -->
		</set>
	</class>


</hibernate-mapping>

 Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.org.model">
	<class name="Student" table="student">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name" column="name" not-null="true"/>
		
		<!--   name指Student类中对应一方的属性名          cascade属性指定级联操作         
		 class指一方的类名                column中的name表示关联的外键      
		 not-null表示此外键不能为空    --> 
		
		<many-to-one name="classes"  class="MyClass" cascade="save-update">
		       <column name="class_id" not-null="true"></column>
		</many-to-one>
	</class>


</hibernate-mapping>

 

测试用例:
   

List<Student> students = session.createQuery("from Student s where s.id in (:ids) ")
			
                 .setParameterList("ids", new Object[]{43,46}).list();
			
                  Iterator<Student> iterator = students.iterator();
	while(iterator.hasNext()){
				
                      Student student = iterator.next();
				
                      System.out.println("学生姓名:"+student.getName());
				
                      System.out.println("该学生所在班级"+student.getClasses().getName());
			}

 

1)若没配batch-size,即<class name="MyClass" table="class">

执行结果:总共执行三条查询语句,其中执行1条学生查询语句,2条班级查询语句

Hibernate: select student0_.id as id1_, student0_.name as name1_, student0_.class_id as class3_1_ from student student0_ where student0_.id in (? , ?)

学生姓名:ccc
Hibernate: select myclass0_.id as id0_0_, myclass0_.name as name0_0_ from class myclass0_ where myclass0_.id=?
该学生所在班级09003

学生姓名:aaa
Hibernate: select myclass0_.id as id0_0_, myclass0_.name as name0_0_ from class myclass0_ where myclass0_.id=?
该学生所在班级09004

 

2)若配batch-size,即<class name="MyClass" table="class" batch-size="3">

执行结果:总共执行2跳查询语句,其中执行1条学生查询语句,执行1条班级查询语句(每3个班级,发一条sql语句)

Hibernate: select student0_.id as id1_, student0_.name as name1_, student0_.class_id as class3_1_ from student student0_ where student0_.id in (? , ?)

学生姓名:ccc
Hibernate: select myclass0_.id as id0_0_, myclass0_.name as name0_0_ from class myclass0_ where myclass0_.id in (?, ?)

该学生所在班级09003
学生姓名:aaa
该学生所在班级09004

 

hibernate抓取策略,batch-szie在集合上的应用


batch-size属性,可以批量加载实体类,
<set name="students" batch-size="3">

 MyClass.hbm.xml

 

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.org.model">
	<class name="MyClass" table="class" >
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name" not-null="true"/>
		
		<!-- set标签中的name为MyClass类中多方对应的属性名        key标签中的column为多方数据库表中的外键字段-->
		<set name="students"  cascade="save-update" inverse="true" batch-size="3">
			<key column="class_id" not-null="true"></key>
			
			<one-to-many class="Student"/>      <!-- class表明set中放的是什么类型的集合 -->
		</set>
	</class>


</hibernate-mapping>

 

测试用例:

List<MyClass> classes = session.createQuery("from MyClass ").list();
			
          Iterator<MyClass> iterator1 = classes.iterator();
			
          while(iterator1.hasNext()){
				
                 MyClass class1 = iterator1.next();
				
                 System.out.println("班级名:" + class1.getName());

				
                 Set<Student> students = class1.getStudents();
				
                 System.out.println("班级人数:" + students.size());
				
                if (students != null && !students.isEmpty()) {
					
                        Iterator<Student> iterator = students.iterator();
					
                          System.out.print("学生姓名:");
					
                         while (iterator.hasNext()) {
						
                                Student student = iterator.next();
						System.out.println(student.getName());
					}
				}
				
			}

  

1)若配batch-size,即:<set name="students" batch-size="3"> 使用set的batch-size属性,这个属性可以明显的减少执行SQL语句数目,因为它执行的是这样的语句:
如果batch-size=10,而集合有13个关联对象,那么它会执行如下语句:
select id,... from table where id in (?,?,?,?,?,?,?,?,?,?)
select id,... from table where id in (?,?,?)
总共2条语句,如果不设置batch-size,就要执行13条SQL语句

执行结果:总共执行2条sql语句,1条班级查询语句,总共三个关联集合或对象,所以1条关联对象查询语句

 

Hibernate: select myclass0_.id as id0_, myclass0_.name as name0_ from class myclass0_

班级名:09002
Hibernate: select students0_.class_id as class3_0_1_, students0_.id as id1_, 
students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id in (?, ?, ?)
班级人数:0
班级名:09003
班级人数:3
学生姓名:bbb
ccc
aaa
班级名:09004
班级人数:3
学生姓名:aaa
ccc
bbb

 1)若不配batch-size,即:<set name="students">

执行结果:

 

Hibernate: select myclass0_.id as id0_, myclass0_.name as name0_ from class myclass0_

班级名:09002
Hibernate: select students0_.class_id as class3_0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id=?
班级人数:0

班级名:09003
Hibernate: select students0_.class_id as class3_0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id=?
班级人数:3
学生姓名:ccc
aaa
bbb

班级名:09004
Hibernate: select students0_.class_id as class3_0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student students0_ where students0_.class_id=?
班级人数:3
学生姓名:ccc
aaa
bbb

 

hibernate.jdbc.fetch_size 和 hibernate.jdbc.batch_size

hibernate.jdbc.fetch_size 50 //读

hibernate.jdbc.batch_size 30 //写

 hiberante.cfg.xml(Oracle ,sql server 支持,mysql不支持)

  

<property name="hibernate.jdbc.fetch_size">50</property>
<property name="hibernate.jdbc.batch_size">30</property>

 

这两个选项非常非常非常重要!!!将严重影响Hibernate的CRUD性能!

 

C = create, R = read, U = update, D = delete

 

Fetch Size 是设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数。

 

例如一次查询1万条记录,对于Oracle的JDBC驱动来说,是不会1次性把1万条取出来的,而只会取出Fetch Size条数,当纪录集遍历完了这些记录以后,再去数据库取Fetch Size条数据。因此大大节省了无谓的内存消耗。当然Fetch Size设的越大,读数据库的次数越少,速度越快;Fetch Size越小,读数据库的次数越多,速度越慢。这有点像平时我们写程序写硬盘文件一样,设立一个Buffer,每次写入Buffer,等Buffer满了以后,一次写入硬盘,道理相同。

 

Oracle数据库的JDBC驱动默认的Fetch Size=10,是一个非常保守的设定,根据我的测试,当Fetch Size=50的时候,性能会提升1倍之多,当Fetch Size=100,性能还能继续提升20%,Fetch Size继续增大,性能提升的就不显著了。

 

因此我建议使用Oracle的一定要将Fetch Size设到50

 

不过并不是所有的数据库都支持Fetch Size特性,例如MySQL就不支持

 

MySQL就像我上面说的那种最坏的情况,他总是一下就把1万条记录完全取出来,内存消耗会非常非常惊人!这个情况就没有什么好办法了 :(

 

Batch Size是设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,有点相当于设置Buffer缓冲区大小的意思。

 

Batch Size越大,批量操作的向数据库发送sql的次数越少,速度就越快。我做的一个测试结果是当Batch Size=0的时候,使用Hibernate对Oracle数据库删除1万条记录需要25秒,Batch Size = 50的时候,删除仅仅需要5秒!!!

分享到:
评论
2 楼 redcoatjk 2014-06-10  
redcoatjk 写道
例子有问题.

my fault.
返回用Iterator导致没有效果
1 楼 redcoatjk 2014-06-10  
例子有问题.

相关推荐

    day36 06-Hibernate抓取策略:set集合上的抓取策略

    为了解决这个问题,Hibernate提供了多种抓取策略,如Eager Loading(急加载)、Batch Fetching(批量加载)和Subselect Fetching(子查询加载)等。 1. Eager Loading:急加载是一种在加载主对象时同时加载其关联...

    Hibernate3性能优化方案

    抓取优化是针对Hibernate如何高效地处理对象之间的关联关系的一种优化方法。它主要包括两部分:如何抓取和何时抓取。 **1. 如何抓取** 抓取方式分为两种:JOIN抓取和SELECT抓取。 - **JOIN抓取**:在SELECT语句中...

    Hibernate中的多表查询及抓取策略

    - **批量抓取**:通过设置`batch-size`属性,例如在`&lt;set&gt;`标签中配置`batch-size="n"`,可以在查询多个主对象时,批量获取其关联的子对象,减少数据库访问次数。 综上所述,Hibernate的多表查询和抓取策略提供了...

    如何提高hibernate性能

    针对这种情况,优化Hibernate的配置和使用策略至关重要。以下是一些提高Hibernate性能的关键点: 1. **初始化集合**: 当业务层需要为Web层提供完整的数据集合时,确保在Session关闭前调用`Hibernate.initialize()...

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

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

    Hibernate JPA

    ### Hibernate JPA 知识点详解 #### 一、Hibernate JPA 概述 **Hibernate**作为当前最为流行的对象关系映射...了解并掌握Hibernate JPA的基本原理及其配置使用方法,对于提高开发效率和代码质量都具有重要意义。

    Hibernate中大量数据的更新

    在 Hibernate 配置文件中,可以设置 `hibernate.jdbc.batch_size` 参数来指定批量抓取的大小。 如何实现批量更新 在 Controller 层,需要将大量数据插入到数据库时,可以使用以下方法: ```java for (int i = 0; ...

    hibernate 配置属性参数详情(全)

    7. **hibernate.default_batch_fetch_size**:默认的批量抓取大小,可以提高性能,常见的推荐值为4、8、16。 8. **hibernate.default_entity_mode**:指定Session使用的实体表示模式,如`dynamic-map`、`dom4j`或`...

    hibernate配置属性参数[定义].pdf

    7. `hibernate.default_batch_fetch_size`:设置默认的批量抓取关联的数量,可以提高性能。推荐的值通常为 4、8 或 16。 8. `hibernate.default_entity_mode`:指定 SessionFactory 打开的 Session 中实体的默认...

    hibernate[1].cfg.xml中配置信息详解

    `hibernate.jdbc.batch_size` **用途**:设置批量更新的大小。此配置项可以用来优化大量数据的更新操作。 **取值**:建议取5到30之间的值。 ##### 3. `hibernate.jdbc.batch_versioned_data` **用途**:启用或...

Global site tag (gtag.js) - Google Analytics