亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Hibernate的延遲加載

jollywing / 2749人閱讀

摘要:非集合屬性非集合屬性的延遲加載相對(duì)比較復(fù)雜。僅通過注解是無法實(shí)現(xiàn)延遲加載的。但是在一對(duì)一關(guān)系中,延遲加載是有陷阱的。這樣一來,就會(huì)立即為配置延遲加載的實(shí)體生成一個(gè)動(dòng)態(tài)代理類。

Hibernate中,延遲加載針對(duì)屬性類別可以分為兩類,一類是延遲屬性加載,另一類是延遲關(guān)聯(lián)實(shí)體加載。

屬性延遲加載

屬性有可以分為兩種類型:一種是集合屬性,一種是非集合屬性(如String、Integer……)。

集合屬性

集合屬性的延遲加載通過PersistentSet、 PersistentList、PersistentBag、PersistentMap、PersistentSortedMap、PersistentSortedSet作為代理類來實(shí)現(xiàn),代理類中保存了session以及owner屬性,owner屬性表示了集合屬性所屬的one側(cè)的實(shí)體。

非集合屬性

非集合屬性的延遲加載相對(duì)比較復(fù)雜。僅通過@Basic(fetch = FetchType.LAZY)注解是無法實(shí)現(xiàn)延遲加載的。需要讓實(shí)體實(shí)現(xiàn)FieldHandled接口,聲明FieldHandler屬性,通過攔截器原理注入對(duì)應(yīng)的FieldHandler屬性,起到類似于上述代理類的作用,F(xiàn)ieldHandler同樣也保持了session,以及需要延遲加載的屬性。下面的代碼實(shí)現(xiàn)了非集合屬性的延遲加載

@Basic(fetch = FetchType.LAZY)
@Column(name="CONTENT")
public String getContent() {
    if (fieldHandler != null) {
        return (byte[]) fieldHandler.readObject(this, "content", content);
    }
    return null;
}
public void setContent(byte[] content) {
    this.content = content;
}
@Override
public void setFieldHandler(FieldHandler handler) {
    this.fieldHandler = handler;
}
@Override
public FieldHandler getFieldHandler() {
    return this.fieldHandler;
}

Hibernate官網(wǎng)對(duì)非結(jié)合屬性的延遲加載有如下的評(píng)論:

Lazy property loading requires buildtime bytecode instrumentation. If your persistent classes are not enhanced, Hibernate will ignore lazy property settings and return to immediate fetching.
A different way of avoiding unnecessary column reads, at least for read-only transactions, is to use the projection features of HQL or Criteria queries. This avoids the need for buildtime bytecode processing and is certainly a preferred solution.

大致的意思就是:應(yīng)該是因?yàn)椋覀儾⑽从玫骄幾g時(shí)字節(jié)碼增強(qiáng)技術(shù)的原因。如果只對(duì)部分property進(jìn)行延遲加載的話,hibernate還提供了另外的方式,也是更為推薦的方式,即HQL或者條件查詢。
更為推薦的方式說白了就是在查詢的時(shí)候就過濾掉不需要的屬性,以下列出HQL和Criterial的兩種實(shí)現(xiàn)方法:

// criterial實(shí)現(xiàn)
criteria.setProjection(
                Projections.projectionList().add(Projections.property("id"), "id")
                        .add(Projections.property("age"), "age")).setResultTransformer(
                Transformers.aliasToBean(User.class));

// HQL實(shí)現(xiàn)
Query query = session.createQuery("select u.id as id,u.age as age from User u where u.id=2");
query.setResultTransformer(Transformers.aliasToBean(User.class));
關(guān)聯(lián)實(shí)體延遲加載

關(guān)聯(lián)實(shí)體延遲加載分兩種情況,一種是多對(duì)一,另一種是一對(duì)一。

多對(duì)一關(guān)聯(lián)

關(guān)聯(lián)實(shí)體是多個(gè)實(shí)體時(shí)(包括一對(duì)多、多對(duì)多):此時(shí)關(guān)聯(lián)實(shí)體將以集合的形式存在,Hibernate 將使用 PersistentSet、PersistentList、PersistentMap、PersistentSortedMap、PersistentSortedSet 等集合來管理延遲加載的實(shí)體。這就是前面所介紹的情形。

一對(duì)一關(guān)聯(lián)

關(guān)聯(lián)實(shí)體是單個(gè)實(shí)體時(shí)(包括一對(duì)一、多對(duì)一):當(dāng) Hibernate 加載某個(gè)實(shí)體時(shí),延遲的關(guān)聯(lián)實(shí)體將是一個(gè)動(dòng)態(tài)生成代理對(duì)象。Hibernate 使用 Javassist 項(xiàng)目動(dòng)態(tài)生成的代理類——當(dāng) Hibernate 延遲加載關(guān)聯(lián)實(shí)體時(shí),將會(huì)采用 Javassist 生成一個(gè)動(dòng)態(tài)代理對(duì)象,這個(gè)代理對(duì)象將負(fù)責(zé)代理“暫未加載”的關(guān)聯(lián)實(shí)體。但是在一對(duì)一關(guān)系中,延遲加載是有陷阱的。一對(duì)一關(guān)聯(lián)一般有兩種形式,一種是主鍵關(guān)聯(lián);另一種是外鍵關(guān)聯(lián)。

主鍵關(guān)聯(lián)

數(shù)據(jù)表Husband,兩列屬性id,name
數(shù)據(jù)表Wife,兩列屬性id,name

Husband實(shí)體:
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
@PrimaryKeyJoinColumn
getWife()
@GenericGenerator(name = "Wife", strategy = "foreign", parameters = { @Parameter(name = "property", value = "husband") })
Wife實(shí)體:
@OneToOne(mappedBy = "wife", fetch = FetchType.LAZY)
getHusband()

以上是hibernate中的配置。其中“optional=false”的配置時(shí)關(guān)鍵,否則即使配置了fetch策略為lazy,也無法做到在獲取husband實(shí)體的時(shí)候延遲加載wife實(shí)體。optional的默認(rèn)值是true,表示關(guān)聯(lián)的實(shí)體可以為null。在一對(duì)一的延遲加載中,hibernate并非一定對(duì)需要延遲加載的實(shí)體生成一個(gè)動(dòng)態(tài)代理對(duì)象,而是當(dāng)被關(guān)聯(lián)的實(shí)體確定不為null時(shí),才會(huì)生成,否則直接將其置為null。所以問題就來了,對(duì)于兩個(gè)通過主鍵關(guān)聯(lián)的一對(duì)一實(shí)體,在獲取到其中一個(gè)實(shí)體后,要判斷與之關(guān)聯(lián)的實(shí)體是否存在,則必須要再查詢一次數(shù)據(jù)庫才可以。這也就是為什么在設(shè)置了延遲加載策略后,hibernate還是立即發(fā)送了一次查詢請(qǐng)求給數(shù)據(jù)庫。
要解決一對(duì)一關(guān)系中的延遲加載,共有兩種方法:一種就是上面提到的,把optional設(shè)置為false,即關(guān)聯(lián)的實(shí)體一定不為null。這樣一來,hibernate就會(huì)立即為配置延遲加載的實(shí)體生成一個(gè)動(dòng)態(tài)代理類。
但是這又存在一個(gè)坑,在創(chuàng)建實(shí)體husband的時(shí)候,其主鍵為null(還未生成),wife的主鍵也為null,此時(shí)save的話,hibernate理論上應(yīng)該先insert husband實(shí)體,然后用生成出來的husband_id作為wife的主鍵進(jìn)行insert??墒屡c愿違,hibernate認(rèn)為此情況違背了optional=false的假設(shè),故會(huì)拋異常IdentifierGenerationException,即wife的id為null。具體原因不太知曉,猜測(cè)可能是因?yàn)槌志没捻樞?,先持久化husband,此時(shí)wife的主鍵為null,但是你又配置了optional=false,故前后矛盾而拋出異常。

外鍵關(guān)聯(lián)

數(shù)據(jù)表Husband,3列屬性id,name, wife_id
數(shù)據(jù)表Wife,兩列屬性id,name
其中husband_id與Husbande中的id關(guān)聯(lián)

Husband實(shí)體:
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "wife_id", , referencedColumnName = "id")
getWife()
Wife實(shí)體:
@OneToOne(mappedBy = "wife", fetch = FetchType.LAZY)
getHusband()

這樣一來,直接可以通過husband中的wife_id的null與否來判斷wife實(shí)體是否為null。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/64770.html

相關(guān)文章

  • Hibernate5.2-5.3版本ManyToOne、OneToOne延遲加載(fetch=L

    摘要:項(xiàng)目使用的版本進(jìn)行開發(fā),里面使用到,而這個(gè)版本自帶的實(shí)現(xiàn)是的版本。這個(gè)版本里面的延遲加載是沒有問題的,當(dāng)你設(shè)置時(shí),關(guān)聯(lián)的對(duì)象在你沒有使用的時(shí)候,是不會(huì)發(fā)出的。這個(gè)問題,在升級(jí)版本后是解決了的。 項(xiàng)目使用springboot的1.5.19版本進(jìn)行開發(fā),里面使用到JPA,而springboot這個(gè)版本自帶的JPA實(shí)現(xiàn)是Hibernate的5.0.12版本。 這個(gè)版本里面的延遲加載是沒有問題...

    blair 評(píng)論0 收藏0
  • JAVA面試題(29)

    摘要:本文首發(fā)于的博客轉(zhuǎn)載請(qǐng)注明出處邏輯分頁和物理分頁的區(qū)別是什么分頁是為了節(jié)省網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量邏輯分頁是將數(shù)據(jù)全部加載到內(nèi)存,再通過后端邏輯控制分頁顯示到前端物理分頁是在數(shù)據(jù)庫層面分部分獲取數(shù)據(jù),通常情況下對(duì)內(nèi)存的壓力較邏輯分頁少是否支持延遲加 ????本文首發(fā)于cartoon的博客????轉(zhuǎn)載請(qǐng)注明出處:https://cartoonyu.github.io/c... Mybatis...

    junbaor 評(píng)論0 收藏0
  • Hibernate最全面試題

    摘要:中怎樣實(shí)現(xiàn)類之間的關(guān)系如一對(duì)多多對(duì)多的關(guān)系中怎樣實(shí)現(xiàn)類之間的關(guān)系如一對(duì)多多對(duì)多的關(guān)系它們通過配置文件中的來實(shí)現(xiàn)類之間的關(guān)聯(lián)關(guān)系的。 Hibernate常見面試題 Hibernate工作原理及為什么要用? Hibernate工作原理及為什么要用? 讀取并解析配置文件 讀取并解析映射信息,創(chuàng)建SessionFactory 打開Sesssion 創(chuàng)建事務(wù)Transation 持久化操作 提...

    張利勇 評(píng)論0 收藏0
  • Hibernate問題集錦

    摘要:查詢照樣寫就行,如下參考問題七中關(guān)于多表連接查詢和返回值集合中對(duì)象問題錯(cuò)誤的查詢語句釋放分析原來是查詢出來的字段并不能自動(dòng)轉(zhuǎn)換為對(duì)象。參考問題八原因原生的語句中返回值為,而語句中的返回值位型的,網(wǎng)上說的主要是兼容而做的。 首先奉上Hibernate3.2 API地址:http://docs.jboss.org/hiberna...Hibernate4.3 API地址:http://do...

    niceforbear 評(píng)論0 收藏0
  • Mybatis常見面試題

    摘要:執(zhí)行沒有,批處理不支持,將所有都添加到批處理中,等待統(tǒng)一執(zhí)行,它緩存了多個(gè)對(duì)象,每個(gè)對(duì)象都是完畢后,等待逐一執(zhí)行批處理。 Mybatis常見面試題 #{}和${}的區(qū)別是什么? #{}和${}的區(qū)別是什么? 在Mybatis中,有兩種占位符 #{}解析傳遞進(jìn)來的參數(shù)數(shù)據(jù) ${}對(duì)傳遞進(jìn)來的參數(shù)原樣拼接在SQL中 #{}是預(yù)編譯處理,${}是字符串替換。 使用#{}可以有效的防止...

    liuchengxu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<