日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hibernate抓取策略

發布時間:2025/5/22 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate抓取策略 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為什么80%的碼農都做不了架構師?>>> ??

6、抓取策略:抓取策略主要是指獲取連接對象的策略。

? ? 6.1、基于XML的抓取

? ? 1.1、基于XML抓取many-to-one

session = HibernateUtil.openSession();/*** 默認情況會發出3條SQL語句,一條取Student,一條取Classroom,一條取Special* many-to-one的默認情況,使用的是延遲加載*/Student stu = session.load(Student.class, 1);System.out.println(stu.getName()+","+stu.getClassroom().getName()+","+stu.getClassroom().getSpecial().getName());

? ? 1.2、設置fetch="join"

session = HibernateUtil.openSession();/*** 默認情況會發出3條SQL語句,一條取Student,一條取Classroom,一條取Special* 通過設置XML中的<many-to-one name="classroom" column="cid" fetch="join"/>* 可以完成對抓取的設置,只會發出一條SQL語句*/Student stu = session.load(Student.class, 1);System.out.println(stu.getName()+","+stu.getClassroom().getName()+","+stu.getClassroom().getSpecial().getName()); <!-- 設置了fetch="join"之后,會連接查詢將對象加載出來 --><many-to-one name="classroom" column="cid" fetch="join"/>

? ? 存在問題:延遲加載失效

session = HibernateUtil.openSession();/*** 使用fetch="join"雖然可以將關聯對象抓取,但是如果不使用關聯對象也會一并查詢出來* 這樣會占用相應的內存*/Student stu = session.load(Student.class, 1);//延遲加載就失效System.out.println(stu.getName());

????1.3、但是fetch="join"無法抓取HQL中的list,如果需要抓取HQL中的list有兩種方法:

????? ? ·設置one這一端對象的batch-size,此時會通過in的語句來加載多條數據。

<hibernate-mapping package="org.pm.hibernate.model"><!-- 設置batch-size="20",在抓取Classroom的時候,會一下抓取20Classroom的記錄 --><class name="Classroom" table="t_classroom" batch-size="20"><id name="id"><generator class="native"/></id> session = HibernateUtil.openSession();/*** 在XML中配置了fetch="join"僅僅只是對load的對象有用,對HQL中查詢的對象無用,* 所以此時會發出查詢班級的SQL,解決這個SQL的問題有兩種方案,* 一種是設置對象的抓取的batch-size* 另一種方案在HQL中指定抓取*/List<Student> stus = session.createQuery("from Student", Student.class).getResultList();for(Student stu:stus) {System.out.println(stu.getName()+","+stu.getClassroom().getName());}

????? ? ·在HQL語句中寫預抓取(特別注意:使用預抓取不支持count(*)查詢)

session = HibernateUtil.openSession();/*** 在XML中配置了fetch="join"僅僅只是對load的對象有用,對HQL中查詢的對象無用,* 所以此時會發出查詢班級的SQL,解決這個SQL的問題有兩種方案,* 一種是設置對象的抓取的batch-size* 另一種方案在HQL中指定抓取,通過在HQL中添加fetch關鍵字完成抓取* 特別注意:如果使用了join fetch就無法使用count(*)*/List<Student> stus = session.createQuery("select stu from "+ "Student stu join fetch stu.classroom", Student.class).getResultList();for(Student stu:stus) {System.out.println(stu.getName()+","+stu.getClassroom().getName());}

? ? 1.4、集合抓取

<!-- 設置fetch="subselect",對于list查詢它會根據查詢的結果來完成對對象的子查詢 --><set name="stus" inverse="true" lazy="extra" fetch="subselect"><key column="cid"/><one-to-many class="Student"/></set> session = HibernateUtil.openSession();List<Classroom> clas = session.createQuery("from Classroom", Classroom.class).getResultList();for(Classroom cla:clas) {System.out.println(cla.getName());/** 抓取集合,默認是select,此時會為每一個班的學生發出sql* 對于通過HQL取班級列表并且獲取相應的學生列表時,fetch="join"就無效了* 第一種方案可以設置set的batch-size來完成批量的抓取* 第二種方案可以設置fetch=subselect,使用subselect會完成根據查詢出來的班級* 進行一次對學生對象的子查詢*/for(Student stu:cla.getStus()) {System.out.print(stu.getName());}}

? ? 對于集合抓取而言,有三種設置方式:select(默認),join,subselect。

? ? 其中在查詢單個對象時,select和subselect完全一樣,都是在需要查詢集合對象時才發出sql,但是join會
????使用連接查詢。

? ? 在查詢列表對象時,select和join一樣(可以通過設置set的batch-size設置抓取的數量)

最佳實踐:很多情況不會設置one-to-many,如果要設置one-to-many可以設置為subselect。

? ? 6.2、基于Annotation的抓取

? ? 1、基于Annotation的many-to-one

session = HibernateUtil.openSession();/*** 對于Annotation的配置而言,默認就是基于join的抓取的,所以只會發出1條SQL*/Student stu = session.load(Student.class, 1);System.out.println(stu.getName()+","+stu.getClassroom().getName()+","+stu.getClassroom().getSpecial().getName()); session = HibernateUtil.openSession();/*** 基于Annotation的配置沒有延遲加載,此時會把所有的關聯對象查詢出來,發出大量的SQL語句*/List<Student> stus = session.createQuery("from Student", Student.class).getResultList();for(Student stu:stus) {System.out.println(stu.getName()+","+stu.getClassroom().getName());} @ManyToOne(fetch=FetchType.EAGER) //LAZY就是XML中select,EAGER就表示XML中的join@JoinColumn(name="cid")public Classroom getClassroom() {return classroom;}public void setClassroom(Classroom classroom) {this.classroom = classroom;} session = HibernateUtil.openSession();/*** 基于Annotation,由于many-to-one的默認抓取策略是EAGER的,所以當抓取Classroom* 時會自動發出多條SQL去查詢相應的Special,此時可以通過join fetch繼續完成對關聯的* 抓取,或者直接將關聯對象的fetch設置為LAZY,但是使用LAZY所帶來的問題是在查詢* 關聯對象時需要發出相應的SQL,很多時候也會影響效率*/List<Student> stus = session.createQuery("select stu from "+ "Student stu join fetch stu.classroom cla join fetch cla.special", Student.class).getResultList();for(Student stu:stus) {System.out.println(stu.getName()+","+stu.getClassroom().getName());}

????可以使用@BatchSize

@Entity @Table(name="t_classroom") @BatchSize(size=20) public class Classroom {private int id;private String name;private int grade;private Set<Student> stus;private Special special;

? ? 2、集合抓取

@OneToMany(mappedBy="classroom")@LazyCollection(LazyCollectionOption.EXTRA)@Fetch(FetchMode.SUBSELECT) //在Annotation中需要通過這種方式才能設置subselectpublic Set<Student> getStus() {return stus;}public void setStus(Set<Student> stus) {this.stus = stus;}@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="spe_id")public Special getSpecial() {

?

轉載于:https://my.oschina.net/pmos/blog/768310

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的Hibernate抓取策略的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。