类关系:  User N~1 Group

测试代码:

  1. System.out.println("1");
  2. List stuList = session.createQuery("from User s where s.password ='123'").list(); //(1)
  3. System.out.println("2");
  4. for(Iterator it = stuList.iterator(); it.hasNext();){
  5. User stu = (User)it.next();
  6. System.out.println("3");
  7. System.out.println("[value]"+stu.getName()); //(2)
  8. System.out.println("[value]"+stu.getGroup().getName()); //(3)
  9. }

执行效果:

(1)查询符合条件的User集合. 发出的SQL为 select  * from test_User where password='123'
(2)不再发出SQL. 使用缓存中的User数据.

(3)迭代User时,检查是否加载过对应User的Group,若无则发出一次SQL:  select * from test_group where group_id=?

     如果User有10个.对应在3个group中. 则发出3条select * from test_group where group_id=?

1
Hibernate: 
    select
        user0_.id as id0_,
        user0_.name as name0_,
        user0_.password as password0_,
        user0_.createTime as createTime0_,
        user0_.updateTime as updateTime0_,
        user0_.group_id as group6_0_
    from
        TEST_User user0_
    where
        user0_.password='123'
2
3
[value]jordan
Hibernate:
    select
        group0_.id as id1_0_,
        group0_.name as name1_0_
    from
        TEST_Group group0_
    where
        group0_.id=?
[value]集团2 
  
3
[value]kobe
[value]集团2
3
[value]james
[value]集团2
//以下继续开始循环遍历
3
[value]张三111
Hibernate:
    select
        group0_.id as id1_0_,
        group0_.name as name1_0_
    from
        TEST_Group group0_
    where
        group0_.id=?
[value]集团1
3
[value]李四111
[value]集团1
3
[value]李四111
[value]集团1
3
[value]AAA
Hibernate:
    select
        group0_.id as id1_0_,
        group0_.name as name1_0_
    from
        TEST_Group group0_
    where
        group0_.id=?
[value]集团3
3
[value]BBB
[value]集团3
3
[value]CCC
[value]集团3
3
[value]a1
Hibernate:
    select
        group0_.id as id1_0_,
        group0_.name as name1_0_
    from
        TEST_Group group0_
    where
        group0_.id=?
[value]集团4
3
[value]a11
[value]集团4
3
[value]a111
[value]集团4
3
[value]b1
Hibernate:
    select
        group0_.id as id1_0_,
        group0_.name as name1_0_
    from
        TEST_Group group0_
    where
        group0_.id=?
[value]集团5
3
[value]b11
[value]集团5
3
[value]b111
[value]集团5

 配置batch-size

<class name="com.test.entity.Group" table="TEST_Group" batch-size="2">

 执行效果

 (1)(2)同上

 (3)在遍历User,并且获取对应的Group时.检测是否加载过对应的数据.若无根据设置的batch-size=2

     发出SQL语句: select * from test_group where group_id in (?,?)  一次查询2个Group放到内存中.

     在此遍历User及其Group时,若内存中无加载过对应数据,则再次发出SQL  select * from test_group where group_id in (?,?)  一次查询2个Group放到内存中.

     如Group的数据最后不足.则使用select * from test_group where group_id =? 进行加载

     即如Group 有5个. 则通过2个2个1个的方式进行查询获取到.

  1. 1
  2. Hibernate:
  3. select
  4. user0_.id as id0_,
  5. user0_.name as name0_,
  6. user0_.password as password0_,
  7. user0_.createTime as createTime0_,
  8. user0_.updateTime as updateTime0_,
  9. user0_.group_id as group6_0_
  10. from
  11. TEST_User user0_
  12. where
  13. user0_.password='123'
  14. 2
  15. 3
  16. [value]jordan
  17. Hibernate:
  18. select
  19. group0_.id as id1_0_,
  20. group0_.name as name1_0_
  21. from
  22. TEST_Group group0_
  23. where
  24. group0_.id in (
  25. ?, ?
  26. )
  27. [value]集团2
  28. 3
  29. [value]kobe
  30. [value]集团2
  31. 3
  32. [value]james
  33. [value]集团2
  34. 3
  35. [value]张三111
  36. [value]集团1
  37. 3
  38. [value]李四111
  39. [value]集团1
  40. 3
  41. [value]李四111
  42. [value]集团1
  43. 3
  44. [value]AAA
  45. Hibernate:
  46. select
  47. group0_.id as id1_0_,
  48. group0_.name as name1_0_
  49. from
  50. TEST_Group group0_
  51. where
  52. group0_.id in (
  53. ?, ?
  54. )
  55. [value]集团3
  56. 3
  57. [value]BBB
  58. [value]集团3
  59. 3
  60. [value]CCC
  61. [value]集团3
  62. 3
  63. [value]a1
  64. [value]集团4
  65. 3
  66. [value]a11
  67. [value]集团4
  68. 3
  69. [value]a111
  70. [value]集团4
  71. 3
  72. [value]b1
  73. Hibernate:
  74. select
  75. group0_.id as id1_0_,
  76. group0_.name as name1_0_
  77. from
  78. TEST_Group group0_
  79. where
  80. group0_.id=?
  81. [value]集团5
  82. 3
  83. [value]b11
  84. [value]集团5
  85. 3
  86. [value]b111
  87. [value]集团5

P.S 注意如果使用iterate进行迭代而非List ,则Batch-size无效.

如下

  1. System.out.println("1");
  2. Iterator iter = session.createQuery(" from Group g where g.name like'集团%'").iterate(); //(1)
  3. System.out.println("2");
  4. while (iter.hasNext()) {
  5. System.out.println("3");
  6. Group g = (Group) iter.next();
  7. System.out.println("4");
  8. System.out.println("[value]" + g.getName()); //(2)
  9. System.out.println("5");
  10. System.out.println("[value]" + g.getUsers().size()); //(3)
  11. }

执行效果

原因的出现是因为

(1)处使用了iterate返回集合.iterate默认会开始发出一条语句:查询所有记录符合条件的user的ID. select id from user where password =?

因为(1)只查询出id , 所以在(2)时. 需要再发出一条SQL获取user的属性数据. select * from user where id=?

这就是iterate很出名的N+1问题.

至于(3)处, 如果group没加载过,每次都会发出一条SQL. select * from group where id=?

所以此情况下, batch-size已无法达到预期效果.

  1. 1
  2. Hibernate:
  3. select
  4. user0_.id as col_0_0_
  5. from
  6. TEST_User user0_
  7. where
  8. user0_.password='123'
  9. 2
  10. 3
  11. 4
  12. Hibernate:
  13. select
  14. user0_.id as id0_0_,
  15. user0_.name as name0_0_,
  16. user0_.password as password0_0_,
  17. user0_.createTime as createTime0_0_,
  18. user0_.updateTime as updateTime0_0_,
  19. user0_.group_id as group6_0_0_
  20. from
  21. TEST_User user0_
  22. where
  23. user0_.id=?
  24. [value]jordan
  25. 5
  26. Hibernate:
  27. select
  28. group0_.id as id1_0_,
  29. group0_.name as name1_0_
  30. from
  31. TEST_Group group0_
  32. where
  33. group0_.id=?
  34. [value]集团2
  35. 3
  36. 4
  37. Hibernate:
  38. select
  39. user0_.id as id0_0_,
  40. user0_.name as name0_0_,
  41. user0_.password as password0_0_,
  42. user0_.createTime as createTime0_0_,
  43. user0_.updateTime as updateTime0_0_,
  44. user0_.group_id as group6_0_0_
  45. from
  46. TEST_User user0_
  47. where
  48. user0_.id=?
  49. [value]kobe
  50. 5
  51. [value]集团2
  52. 3
  53. 4
  54. Hibernate:
  55. select
  56. user0_.id as id0_0_,
  57. user0_.name as name0_0_,
  58. user0_.password as password0_0_,
  59. user0_.createTime as createTime0_0_,
  60. user0_.updateTime as updateTime0_0_,
  61. user0_.group_id as group6_0_0_
  62. from
  63. TEST_User user0_
  64. where
  65. user0_.id=?
  66. [value]james
  67. 5
  68. [value]集团2
  69. 3
  70. 4
  71. Hibernate:
  72. select
  73. user0_.id as id0_0_,
  74. user0_.name as name0_0_,
  75. user0_.password as password0_0_,
  76. user0_.createTime as createTime0_0_,
  77. user0_.updateTime as updateTime0_0_,
  78. user0_.group_id as group6_0_0_
  79. from
  80. TEST_User user0_
  81. where
  82. user0_.id=?
  83. [value]张三111
  84. 5
  85. Hibernate:
  86. select
  87. group0_.id as id1_0_,
  88. group0_.name as name1_0_
  89. from
  90. TEST_Group group0_
  91. where
  92. group0_.id=?
  93. [value]集团1
  94. 3
  95. 4
  96. Hibernate:
  97. select
  98. user0_.id as id0_0_,
  99. user0_.name as name0_0_,
  100. user0_.password as password0_0_,
  101. user0_.createTime as createTime0_0_,
  102. user0_.updateTime as updateTime0_0_,
  103. user0_.group_id as group6_0_0_
  104. from
  105. TEST_User user0_
  106. where
  107. user0_.id=?
  108. [value]李四111
  109. 5
  110. [value]集团1
  111. 3
  112. 4
  113. Hibernate:
  114. select
  115. user0_.id as id0_0_,
  116. user0_.name as name0_0_,
  117. user0_.password as password0_0_,
  118. user0_.createTime as createTime0_0_,
  119. user0_.updateTime as updateTime0_0_,
  120. user0_.group_id as group6_0_0_
  121. from
  122. TEST_User user0_
  123. where
  124. user0_.id=?
  125. [value]李四111
  126. 5
  127. [value]集团1
  128. 3
  129. 4
  130. Hibernate:
  131. select
  132. user0_.id as id0_0_,
  133. user0_.name as name0_0_,
  134. user0_.password as password0_0_,
  135. user0_.createTime as createTime0_0_,
  136. user0_.updateTime as updateTime0_0_,
  137. user0_.group_id as group6_0_0_
  138. from
  139. TEST_User user0_
  140. where
  141. user0_.id=?
  142. [value]AAA
  143. 5
  144. Hibernate:
  145. select
  146. group0_.id as id1_0_,
  147. group0_.name as name1_0_
  148. from
  149. TEST_Group group0_
  150. where
  151. group0_.id=?
  152. [value]集团3
  153. 3
  154. 4
  155. Hibernate:
  156. select
  157. user0_.id as id0_0_,
  158. user0_.name as name0_0_,
  159. user0_.password as password0_0_,
  160. user0_.createTime as createTime0_0_,
  161. user0_.updateTime as updateTime0_0_,
  162. user0_.group_id as group6_0_0_
  163. from
  164. TEST_User user0_
  165. where
  166. user0_.id=?
  167. [value]BBB
  168. 5
  169. [value]集团3
  170. 3
  171. 4
  172. Hibernate:
  173. select
  174. user0_.id as id0_0_,
  175. user0_.name as name0_0_,
  176. user0_.password as password0_0_,
  177. user0_.createTime as createTime0_0_,
  178. user0_.updateTime as updateTime0_0_,
  179. user0_.group_id as group6_0_0_
  180. from
  181. TEST_User user0_
  182. where
  183. user0_.id=?
  184. [value]CCC
  185. 5
  186. [value]集团3
  187. 3
  188. 4
  189. Hibernate:
  190. select
  191. user0_.id as id0_0_,
  192. user0_.name as name0_0_,
  193. user0_.password as password0_0_,
  194. user0_.createTime as createTime0_0_,
  195. user0_.updateTime as updateTime0_0_,
  196. user0_.group_id as group6_0_0_
  197. from
  198. TEST_User user0_
  199. where
  200. user0_.id=?
  201. [value]a1
  202. 5
  203. Hibernate:
  204. select
  205. group0_.id as id1_0_,
  206. group0_.name as name1_0_
  207. from
  208. TEST_Group group0_
  209. where
  210. group0_.id=?
  211. [value]集团4
  212. 3
  213. 4
  214. Hibernate:
  215. select
  216. user0_.id as id0_0_,
  217. user0_.name as name0_0_,
  218. user0_.password as password0_0_,
  219. user0_.createTime as createTime0_0_,
  220. user0_.updateTime as updateTime0_0_,
  221. user0_.group_id as group6_0_0_
  222. from
  223. TEST_User user0_
  224. where
  225. user0_.id=?
  226. [value]a11
  227. 5
  228. [value]集团4
  229. 3
  230. 4
  231. Hibernate:
  232. select
  233. user0_.id as id0_0_,
  234. user0_.name as name0_0_,
  235. user0_.password as password0_0_,
  236. user0_.createTime as createTime0_0_,
  237. user0_.updateTime as updateTime0_0_,
  238. user0_.group_id as group6_0_0_
  239. from
  240. TEST_User user0_
  241. where
  242. user0_.id=?
  243. [value]a111
  244. 5
  245. [value]集团4
  246. 3
  247. 4
  248. Hibernate:
  249. select
  250. user0_.id as id0_0_,
  251. user0_.name as name0_0_,
  252. user0_.password as password0_0_,
  253. user0_.createTime as createTime0_0_,
  254. user0_.updateTime as updateTime0_0_,
  255. user0_.group_id as group6_0_0_
  256. from
  257. TEST_User user0_
  258. where
  259. user0_.id=?
  260. [value]b1
  261. 5
  262. Hibernate:
  263. select
  264. group0_.id as id1_0_,
  265. group0_.name as name1_0_
  266. from
  267. TEST_Group group0_
  268. where
  269. group0_.id=?
  270. [value]集团5
  271. 3
  272. 4
  273. Hibernate:
  274. select
  275. user0_.id as id0_0_,
  276. user0_.name as name0_0_,
  277. user0_.password as password0_0_,
  278. user0_.createTime as createTime0_0_,
  279. user0_.updateTime as updateTime0_0_,
  280. user0_.group_id as group6_0_0_
  281. from
  282. TEST_User user0_
  283. where
  284. user0_.id=?
  285. [value]b11
  286. 5
  287. [value]集团5
  288. 3
  289. 4
  290. Hibernate:
  291. select
  292. user0_.id as id0_0_,
  293. user0_.name as name0_0_,
  294. user0_.password as password0_0_,
  295. user0_.createTime as createTime0_0_,
  296. user0_.updateTime as updateTime0_0_,
  297. user0_.group_id as group6_0_0_
  298. from
  299. TEST_User user0_
  300. where
  301. user0_.id=?
  302. [value]b111
  303. 5
  304. [value]集团5

hibernate.jdbc.fetch_size 和 hibernate.jdbc.batch_size

摘自:http://dongruan00.iteye.com/blog/1835081

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 设置外连接抓取树的最大深度

取值. 建议设置为03之间

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

Hibernate 抓取策略fetch-2 (批量抓取batch-size以及hibernate.jdbc.fetch_size、hibernate.jdbc.batch_size)的更多相关文章

  1. Hibernate之加载策略(延迟加载与即时加载)和抓取策略(fetch)

    假设现在有Book和Category两张表,表的关系为双向的一对多,表结构如下: 假设现在我想查询id为2的那本书的书名,使用session.get(...)方法: Session session=H ...

  2. python动态网页爬取——四六级成绩批量爬取

    需求: 四六级成绩查询网站我所知道的有两个:学信网(http://www.chsi.com.cn/cet/)和99宿舍(http://cet.99sushe.com/),这两个网站采用的都是动态网页. ...

  3. 【Hibernate 8】Hibernate的调优方法:抓取策略

    在上一篇博客中,介绍了Hibernate的缓存机制.合理的配置缓存,可以极大程度上优化Hibernate的性能.这篇博客,介绍另外一个调优方式:抓取策略. 一.什么是抓取策略 抓取策略(fetchin ...

  4. 029 hibernate抓取策略

    实例A引用实例B,B如果是代理的话(比如多对一关联中):如果遍历A的查询结果集(假设有10条记录),在遍历A的时候,访问B变量,将会导致n次查询语句的发出!这个时候,如果在B一端的class上配置ba ...

  5. Hibernate框架笔记04HQL_QBC查询详解_抓取策略优化机制

    目录 1. Hibernate的查询方式 1.1 方式一:OID查询 1.2 方式二:对象导航查询 1.3 方式三:HQL方式 1.4 方式四:QBC查询 1.5 方式五:SQL查询 2. 环境搭建 ...

  6. Hibernate的抓取策略(优化)

    延迟加载的概述 什么是延迟加载 延迟加载:lazy(懒加载).执行到该行代码的时候,不会发送语句去进行查询,在真正使用这个对象的属性的时候才会发送SQL语句进行查询. 延迟加载的分类 l  类级别的延 ...

  7. 【转】Hibernate 原汁原味的四种抓取策略

    最近在研究 Hibernate 的性能优化的时候碰到了"抓取策略", 由于以前没有详细的研究过, 所以到处找资料, 但是无论从一些讲 Hibernate 书籍,还是他人 Blog ...

  8. Hibernate 原汁原味的四种抓取策略(转)

    原文出处:http://www.cnblogs.com/rongxh7/archive/2010/05/12/1733088.html     尊重原作者,访问原创地址 最近在研究 Hibernate ...

  9. java:Hibernate框架4(延迟加载(lazy),抓取(fetch),一级缓存,get,load,list,iterate,clear,evict,flush,二级缓存,注解,乐观锁和悲观锁,两者的比较)

    1.延时加载和抓取: hibernate.cfg.xml: <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-co ...

  10. hibernate抓取策略

    抓取策略(fetching strategy) 是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对象的策略.抓取策略可以在O/R映射的 ...

随机推荐

  1. 即使连网了ping也会失败

    /*************************************************************************** * 即使连网了ping也会失败 * 说明: * ...

  2. struts2 中的 result 返回类型是 json 的配置问题

    struts2 中的 result 返回类型是 json 的配置问题 1.引入包(本文中的包全部引自struts-2.1.8.1\lib): struts2-json-plugin-2.1.8.1.j ...

  3. 图像处理之image stitching

    背景介绍 图像拼接是一项应用广泛的图像处理技术.根据特征点的相互匹配,可以将多张小视角的图像拼接成为一张大视角的图像,在广角照片合成.卫星照片处理.医学图像处理等领域都有应用.早期的图像拼接主要是运用 ...

  4. C 语言中 free() 函数简单分析

    又是一个睡不着的夜晚,现在是凌晨03:16,不知道是不是感冒的原因,头脑并不是清醒,但是就是睡不着.摸着黑打开电脑,洗了杯子抓了点茶叶,然后打开饮水机电源.舍友们都睡着了,我戴着耳机听着轻音乐,也能听 ...

  5. Android项目——电话拨号器

    因为应用要使用手机的电话服务,所以要在清单文件AndroidManifest.xml中添加电话服务权限: <?xml version="1.0" encoding=" ...

  6. html5图片懒加载

    http://www.178.com/s/js/jquery.lazyload.min.js

  7. awesome-nlp

    awesome-nlp  A curated list of resources dedicated to Natural Language Processing Maintainers - Keon ...

  8. C#代码:用事件模式实现通知

    事件提供了一种标准的机制来通知监听者..NET的事件模式使用了事件语法来实现观察者模式.任意数量的客户对象都可以将自己的处理函数注册到事件上,然后处理这些事件.这些客户对象不需要再编译期就给出.时间也 ...

  9. postgreSQL 时间线

    “时间线”(Timeline)是PG一个很有特色的概念,在备份恢复方面的文档里面时有出现.但针对这个概念的详细解释却很少,也让人不太好理解,我们在此仔细解析一下. 时间线的引入 为了理解引入时间线的背 ...

  10. C#综合揭秘——深入分析委托与事件

    http://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html 引言 本篇文章将为你介绍一下 Delegate 的使用方式,逐渐揭开 C ...