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抓取策略的全部內容,希望文章能夠幫你解決所遇到的問題。