java 板


LINE

※ 引述《cyclone350 (老子我最神)》之铭言: : 最近利用空档在练习 hibernate (进度缓慢) : 因为这问题想了很久,在网路上也不知道关键字是甚麽,看了一些 document 也没头绪 : 所以就上来请教各位前辈 : 我使用的是 spring + hibernate : 首先 hibernate 是一个 ORM framework。 : 如果我们要 select,利用他提供的 libery 就可以直接存取。 : 要查询物件也很简单,例如: : String hql = "from people"; : List<people> peoplesss = this.getSessionTemplete().creatQuery(hql).list(); : 就可以得到这些Entity,相反的 insert 跟 delete 也类似 : 问题来啦,假设这是美食猎人世界的系统资料库,如果只是用 from people, : 则这个 List 的 size 可能好几百亿,这下不得了。 : 不过 hibernate 可以设定 pageSize 跟 pageNum 之类的东西,可以设定一次只拿到 n 笔 : 问题是 spring 提供的 hibernateTemplete 并没有这个功能‧‧‧ : 好家在 google 大神跟我说 hibernateTemplete 有一个 callbackHibernate 方法, : 所以此问题就解决了。 问题的解决方式很多,你用了比较曲折离奇的callbackHibernate 方法一:由hibernateTemplate中取得sessionFactory後再取得HibernatSession 方法二:直接使用HibernateDaoSupport,就有getSession : 接下来要设定关联资料库 : 假设美食世界的人有三种,美食猎人,厨师,一般人, : 我们可以增加一个 Table 名为 FOOD_TAG。 : 并且在 PEOPLE 的 table 增加一个 FK 名为 TAG,对应到 FOOD_TAG 的 PK, : 所以我们在 PEOPLE 的 Entity 要设定一个 @ManyToOne 对应到 FOOD_TAG : 而 FOOD_TAG 的 Entity 要设定一个 @OneToMany 对应到 PEOPLE。 : 这样想要知道属於美食猎人Tag的人有哪些,只需要从 FOOD_TAG 的 Entity 拿到 people : 的 list 就好了。 老实说,你这个例子让我百思不得其解 这明明只是一个 Enum 的物件,为何要提出来变另一个table people 底下的一个或多个属性就解决的问题,而且还做成双向链节的关连 : 问题来了,如果我只需要拿到 Tag 的名称,例如: : Tag tag = getHibernateTemplete(). : createQuery("from tag t where t.name = '一般人'"); : String tagName = tag.getName(); : 那这样还需要抓取 people List 吗? : 还好可以设定 fetch lazy 来解决这问题,我可以等到要 getPeopleList 时才 query : (不过 session 不能关啦,或是要设定其他的) : 不过又有问题了,假设我要 getPeopleList,他会一次给我全部的人, : 假设分类在 "一般人" 的 People 有 60 亿人,那我的 memory 岂不就爆掉了。 : 於是我翻书,请 google 搜寻此类问题,皆找不到 OneToMany 的限制用法 : 我想要 OneToMany 可以想一般平常的 query 可以设定 maxSize 或是 page 的概念 : 不过 google 似乎也没找到 ... 这是设计上严重的错误阿,你把巨量资料设计在属性之下? 同上,这个问题,你把tag作为people的一个属性就不会有这种问题 : 另外本来想用 FK 当 where 条件当 query,然後就用一开始的方法。 : 可是在 entity 的 FK 是隐藏的 (joinColumn)。 : 想请问有没有此类方法可以解? Annotation 要怎麽设定才会有这样的效果 : 看过很多网站都没讲这问题 当然,因为你正使用了一个不合理的方式在查询资料,事实上没这个问题的 你只要稍微改动一下你取得资料方式 方式一: select people from TAG as tag inner join tag.peopleList as people where tag.name = '一般人' 用PEOPLE 的List来接,并设定setFirstResult / setMaxResults 方式二:from PEOPLE as people inner join people.tag as tag where tag.name = '一般人' 两者都用PEOPLE 的List来接,并设定setFirstResult / setMaxResults 这儿同时显示,只要单向链结,就可以完成你的需求,双向的设定应不需要 : 有看到一个网页有用 @Size(max=30) 这样,但是我的专案根本没有 @Size : 另外还有一个问题,我还没自己试过,请问 Entity 的 @oneToMany 之类的会有 : 连锁效应吗? : 例如 A -> B -> C -> D <- A : A 对 B , 一对多 : B 对 C , 一对多 : C 对 D , 一对多 : A 对 D , 一对多 : 假设我都是 fetch eager 的话 : 会在 query A 的时候,把 B 一起 query。 : 因为 B -> C,hibernate 会顺便 query C 吗? : 然後 C -> D 再 query D ? : 假设我要拿到D : 就直接 a.getB().get(0).getC().get(0).getD() ? : 这样找一个资料,数量级大一点的话,hibernate 不就死掉了吗? : 文有点长,看不董跟我说我再解释一下,文笔有点不顺。 这儿我要强调一下 Hibernate 是一个重视设计的 framework 任何关连的设计,都要考量着资料量,资料变动性,使用不同的策略 任何一个资料量过大的关连,都会立刻造成OOM,没有例外 你这个问题,如果你采用Lazy的方式,慢慢的get.get.get自然是如此 而这问题我会采用 DAO的方式来解决 直接将取得 D的过程写成一组 HQL,条件下去直接取出 DAO.getD() Lazy功能是给懒人用的,懒人是不能写资料量太大,或是太难的系统 针对大量的资料,设计时就要考量负载了,在取资料时,更要一针见血 高变动,大量的资料,就是用StatelessSession + dao 做为取值策略 低变动,交易性的资料,才用StatefulSession + cache为策略 Hibernate 要学好,就要先自宫掉关连资料库的设计方式 最好,在熟练前也不要摸Spring,在Spring下的Hibernate太容易了 --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 118.168.111.216 ※ 编辑: abola921 来自: 118.168.111.216 (02/25 00:51)
1F:推 PsMonkey:看来我还是乖乖地付钱给 GAE 用 BitTable 就好 [死] 02/25 12:07
2F:推 cyclone350:明白,当初已经用DAO写HQL解决问题了!! 02/25 12:43
3F:→ phstudy:第一次听过lazy fetching是设计给懒人用的 = = 02/25 16:23
这点我得解释一下原因,lazy不可否认,他真的很好用!! 一路用过来,随着系统渐渐庞大,lazy的使用开始造成问题 首先,使用lazy的最大前提是『HibernateSession』不能close不能断 光是这点,就让维护的人很头大了,接到issue的一方,要去抓断在那 先不提是那一方的不成熟,解决问题方绝对是骂到翻过来 再来,lazy的方便,就是有如原文所提,要取得资料,写程式你很容易 就会写成 a.getB().getC().getD() (这很合理,也符合罗辑) 但这段程式码的背後,隐含的就是hibernate不断的在进行query 长久下来,其实也不用多久,一个半年的专案全使用lazy在写的话, 你就会莫名奇秒,效能怎麽就是越来越差,把show_sql一打开来,没几 个动作就出现10M以上的SQL。 到这时才警觉到不可以太过依赖lazy时都为时已晚了。 我用这字眼并没有其它意思,单单就对字面解释,跟不建议对他依赖 ※ 编辑: abola921 来自: 118.168.111.216 (02/25 22:27)
4F:→ qrtt1:conversation 完就能关了,快慢没有绝对,要依profiling为准 02/26 00:32
5F:→ qrtt1:过长的 method chaining 应该建议改写,或提供直接的query 02/26 00:35
6F:推 phstudy:lazy fetching在collection上可以减少不必要的join 02/26 10:04
7F:→ phstudy:在LOB上可以减少不必要的资料传输 02/26 10:06
8F:→ phstudy:hibernate 3中elementCollection, OneToMany, ManyToMany 02/26 11:38
9F:→ phstudy:预设皆为lazy fetching, 目的就是避免一次捞太多资料 02/26 11:40
10F:→ abola921:lazy是没有解答中的最佳解,而且能让程式码更易维护 02/26 11:59
11F:→ abola921:但在hibernate团队管理中,lazy的使用一直是问题 02/26 12:07
12F:→ abola921:因太容易使用,没人觉得自己的code有效能风险 02/26 12:10
13F:→ abola921:在tuning时,别人的code,很难一眼看是出proxy object 02/26 12:12
/* tuning点 */ public void processPeople(People p){ log.debug( p.getCLass() ); } People people = (People) hibernateSession.load( People.class, "who" ); processPeople( people ); /* 结果为 People的proxy class */ People people = new People(); processPeople( people ); /* 结果为 People.class */ ※ 编辑: abola921 来自: 140.109.20.106 (02/26 12:26) ※ 编辑: abola921 来自: 140.109.20.106 (02/26 12:27)
14F:→ abola921:以管理专案的立场,多人的专案lazy的使用必需有所控制 02/26 12:30







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:BuyTogether站内搜寻

TOP