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

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

hbm.xml

classes.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.model">
    <class name="Classes" table="classes_join" batch-size="3">
        <id name="id" column="id" type="java.lang.Integer">
            <generator class="native" />
        </id>
        <property name="name" column="name" type="java.lang.String" />
        <set name="students" >
            <key column="class_id" />
            <one-to-many class="com.model.Student" />
        </set>
    </class>

</hibernate-mapping>

Student.hbm.xml

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.model">
    <class name="Student" table="student_join" >
        <id name="id" column="id" type="java.lang.Integer">
            <generator class="native" />         
        </id>
        <property name="name" column="name" length="50" type="java.lang.String" />
        <many-to-one name="classes" column="class_id" ></many-to-one>
    </class>

</hibernate-mapping>

测试用例:
    List stuList = session.createQuery("from Student s where s.id in (:ids)")
                         .setParameterList("ids", new Object[]{1,10})
                         .list();
    for(Iterator it = stuList.iterator(); it.hasNext();){
     Student stu = (Student)it.next();
     System.out.println(stu.getName());
     System.out.println(stu.getClasses().getName());
    }

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

执行结果:执行2条班级查询语句

Hibernate: select student0_.id as id1_, student0_.name as name1_, student0_.class_id as class3_1_ from student_join student0_ where student0_.id in (? , ?)
学生1
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes_join classes0_ where classes0_.id=?
高一(1)班
学生1
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes_join classes0_ where classes0_.id=?
高一(2)班

2)若配batch-size,即<class name="Classes" table="classes_join" batch-size="5">

执行结果:执行1条班级查询语句(每5个班级,发一条sql语句)

Hibernate: select student0_.id as id1_, student0_.name as name1_, student0_.class_id as class3_1_ from student_join student0_ where student0_.id in (? , ?)
学生1
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes_join classes0_ where classes0_.id in (?, ?)
高一(1)班
学生1
高一(2)班

===================================

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


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

hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.model">
    <class name="Classes" table="classes_join" >
        <id name="id" column="id" type="java.lang.Integer">
            <generator class="native" />
        </id>
        <property name="name" column="name" type="java.lang.String" />
        <set name="students" batch-size="5" >
            <key column="class_id" />
            <one-to-many class="com.model.Student" />
        </set>
    </class>

</hibernate-mapping>

测试用例:

List classList = session.createQuery("from Classes").list();
    for(Iterator iter = classList.iterator(); iter.hasNext();){
     Classes c = (Classes)iter.next();
     System.out.println("Class.name=" + c.getName());
     Set stuSet = c.getStudents();
     System.out.println(stuSet.size());
     if(stuSet != null && !stuSet.isEmpty()){
      for(Iterator it = stuSet.iterator(); it.hasNext();){
       Student s = (Student) it.next();
       System.out.println("student.name=" + s.getName());
      }
     }
    }

加了 <set name="students" batch-size="5" > //每5条,做一次查询
如下:

Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id in (?, ?, ?, ?, ?)

Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id in (?, ?, ?, ?)

=================================

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秒!!!

//
我们通常不会直接操作一个对象的标识符(identifier), 因此标识符的setter方法应该被声明为私有的(private)。这样当一个对象被保存的时候,只有Hibernate可以为它分配标识符。 你会发现Hibernate可以直接访问被声明为public,private和protected等不同级别访问控制的方法(accessor method)和字段(field)。 所以选择哪种方式来访问属性是完全取决于你,你可以使你的选择与你的程序设计相吻合。

所有的持久类(persistent classes)都要求有无参的构造器(no-argument constructor); 因为Hibernate必须要使用Java反射机制(Reflection)来实例化对象。构造器(constructor)的访问控制可以是私有的(private), 然而当生成运行时代理(runtime proxy)的时候将要求使用至少是package级别的访问控制,这样在没有字节码编入 (bytecode instrumentation)的情况下,从持久化类里获取数据会更有效率一些。

hibernate.max_fetch_depth 设置外连接抓取树的最大深度

3之间

就是每次你在查询时,会级联查询的深度,譬如你对关联vo设置了eager的话,如果fetch_depth值太小的话,会发多很多条sql

batch_size 和 fetch_size作用的更多相关文章

  1. 深度学习中的batch的大小对学习效果的影响

    Batch_size参数的作用:决定了下降的方向 极端一: batch_size为全数据集(Full Batch Learning): 好处: 1.由全数据集确定的方向能够更好地代表样本总体,从而更准 ...

  2. Error querying database. Cause: java.lang.IllegalArgumentException:Failed to decrypt.(错误笔记)

    java.lang.IllegalArgumentException:Failed to decrypt 从错误可以看出,解密失败. 原因是你在数据库连接配置的地方,设置了加密.即: config.d ...

  3. Hibernate 抓取策略fetch-2 (批量抓取batch-size以及hibernate.jdbc.fetch_size、hibernate.jdbc.batch_size)

    类关系: User N~1 Group 测试代码: System.out.println("1"); List stuList = session.createQuery(&quo ...

  4. hibernate的速度问题--hibernate.jdbc.fetch_size和 hibernate.jdbc.batch_size

    hibernate的速度问题 这点我也疑惑过,最初应用hibernate的项目,我也感觉速度很慢,知道后来才知道问题的所在.       其实hibernate的速度性能并不差,比起jdbc来说,又是 ...

  5. caffe中各层的作用:

    关于caffe中的solver: cafffe中的sover的方法都有: Stochastic Gradient Descent (type: "SGD"), AdaDelta ( ...

  6. if __name__== "__main__" 的意思(作用)python代码复用

    if __name__== "__main__" 的意思(作用)python代码复用 转自:大步's Blog  http://www.dabu.info/if-__-name__ ...

  7. (转载)linux下各个文件夹的作用

    linux下的文件结构,看看每个文件夹都是干吗用的/bin 二进制可执行命令 /dev 设备特殊文件 /etc 系统管理和配置文件 /etc/rc.d 启动的配置文件和脚本 /home 用户主目录的基 ...

  8. github中的watch、star、fork的作用

    [转自:http://www.jianshu.com/p/6c366b53ea41] 在每个 github 项目的右上角,都有三个按钮,分别是 watch.star.fork,但是有些刚开始使用 gi ...

  9. web.xml中welcome-file-list的作用

    今天尝试使用struts2+ urlrewrite+sitemesh部署项目,结果发现welcome-file-list中定义的欢迎页不起作用: <welcome-file-list> & ...

随机推荐

  1. 线程安全集合 ConcurrentDictionary<TKey, TValue> 类

    ConcurrentDictionary<TKey, TValue> 类 [表示可由多个线程同时访问的键/值对的线程安全集合.] 支持 .NET Framework 4.0 及以上. 示例 ...

  2. DDD:Command模式的好处

    背景 会有朋友问我为啥用命令模式(Command Pattern)组织应用层,先看看MartinFowler咋说:http://martinfowler.com/bliki/CommandOrient ...

  3. [Design Patterns] 3. Software Pattern Overview

    When you're on the way which is unknown and dangerous, just follow your mind and steer the boat. 软件模 ...

  4. cp: omitting directory”错误

    在linux下拷贝的时候有时候会出现cp:omitting directory的错误 , 是因为目录下面还有子目录,不能直接拷贝 解决办法: 命令:cp -r 

  5. centos nfs配置--转载

    http://www.centos.org/docs/5/html/Deployment_Guide-en-US/s1-nfs-client-config.html 18.6. NFS Server ...

  6. Bucky – 免费开源的实时用户监控工具

    Bucky 是一个开源的实时用户监控工具,用于衡量用户在浏览器中使用 Web 应用程序时的性能.它可以自动测量你的网页需要多长时间来加载,Ajax 请求需要多长时间和各个函数需要实行多久. 您可能感兴 ...

  7. LeetCode——Find Median from Data Stream

    Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...

  8. jquery.idTabs使用方法

    idTabs是基于Jquery编写封装的一个插件,主要用于实现选项卡功能,它操作简单,只需到官网:http://www.sunsean.com/idTabs/下载插件JS脚本文件,并引用到网站中即可 ...

  9. C#字符串的恒定性

    string str1="aa"; string str2="aa"; str1,str2,变量所指向的堆空间的地址是一样的.栈空间的内容是不一样的. //ne ...

  10. winform去掉右上角关闭按钮

    一种方法是可以在窗体的属性面板将窗体的 ControlBox属性设置为false,或者在窗体的构造函数中这样写: public Form1() { InitializeComponent(); thi ...