国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設(shè)計 > 正文

淺談Hibernate懶加載與org.hibernate.LazyInitializationException

2019-11-09 13:28:11
字體:
供稿:網(wǎng)友

何為懶加載

懶加載又稱延遲加載,是當在真正需要數(shù)據(jù)的時候,才真正執(zhí)行數(shù)據(jù)加載操作。也就是說,當使用到對象的具體屬性時,才進行加載。

舉個例子來說,一本書(Books)有很多章節(jié)(Chapters),一般加載數(shù)據(jù)的時候,加載Books的同時會同時把Chapters加載上來,而懶加載就是加載Books的屬性時不會將Books中的Chapters立刻加載上來,只有在使用到Chapters中的屬性時,才將Chapters加載出來。

@Entity@Tablepublic class Books { PRivate int id; private String name; private Set<Chapters> chapters = new HashSet<Chapters>(); @Id @GeneratedValue(strategy=GenerationType.AUTO) public int getId() { return id; } public void setId(int id) { this.id = id; } @Column public String getName() { return name; } public void setName(String name) { this.name = name; } @OneToMany(targetEntity=Chapters.class,mappedBy="book") public Set<Chapters> getChapters() { return chapters; } public void setChapters(Set<Chapters> chapters) { this.chapters = chapters; } public Books() { super(); } public Books(String name) { super(); this.name = name; }}@Entity@Tablepublic class Chapters { private int id; private int number; private Books book; @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column public int getId() { return id; } public void setId(int id) { this.id = id; } @Column public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } @ManyToOne(targetEntity=Books.class) public Books getBook() { return book; } public void setBook(Books book) { this.book = book; } public Chapters() { super(); } public Chapters(int number, Books book) { super(); this.number = number; this.book = book; }}

代理模式(Proxy Pattern)

理解Hibernate懶加載之前,需要簡單了解什么是代理模式。

代理模式就是為其他對象提供一種代理以控制對這個對象的訪問。以一段加載圖片的代碼為例。

public interface Image { public void load();}

創(chuàng)建一個背景圖(Background)需要耗時2.333秒

public class Background implements Image { public Background() { super(); try { Thread.sleep(2333); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void load() { System.out.println("加載圖片中..."); }}

代理類如下

public class ImageProxy implements Image { private Image image; public ImageProxy(Image image) { super(); this.image = image; } @Override public void load() { if (null == image) { image = new Background(); } image.load(); }}public class Test { public static void main(String[] args) { long startTime = System.currentTimeMillis(); Image imageProxy = new ImageProxy(null); long endTime = System.currentTimeMillis(); System.out.println("生成代理耗時:" + (endTime - startTime)); imageProxy.load(); long endTime2 = System.currentTimeMillis(); System.out.println("訪問耗時:" + (endTime2 - startTime)); }}/*生成代理耗時:0加載圖片中...訪問耗時:2335*/

Background的創(chuàng)建被推遲到使用時才創(chuàng)建,優(yōu)點顯而易見: * 提高了獲取Background對象的系統(tǒng)性能。 * 減少了對象在內(nèi)存中存在的時間,節(jié)約了系統(tǒng)內(nèi)存的開銷。 * 除此之外,倘若在Test程序中不調(diào)用imageProxy的load()方法,在這種情況下,使用代理模式就可以不創(chuàng)建Background對象,打打提高了系統(tǒng)的運行性能。

這里僅談與懶加載有關(guān)的部分代理模式內(nèi)容,其他內(nèi)容不再闡述。

Hibernate懶加載與代理模式(Proxy Pattern)

Hibernate懶加載所采用的設(shè)計模式便是代理模式,因此在很多情況下能節(jié)約很大的系統(tǒng)開銷,上面已經(jīng)說明,這里不再闡述。

懶加載特性與org.hibernate.LazyInitializationException

明白了Hibernate懶加載與代理模式后,對于org.hibernate.LazyInitializationException也就明白了。由于懶加載的特性,在Hibernate session范圍之外訪問未初始化的集合或者代理都會拋出org.hibernate.LazyInitializationException。因此,在Session的范圍之內(nèi)訪問的集合或代理即可解決該問題。

這里博主給出三種解決方案,僅供參考。

解決方案一: 不使用懶加載

在配置文件或注解中,將懶加載設(shè)置為fetch=FetchType.EAGER或false。

這種做法,可能會把不需要的數(shù)據(jù)也加載上來,影響應用性能。

解決方案二: Open Session In View模式

利用過濾器(Filter),在用戶請求結(jié)束、頁面生成結(jié)束時關(guān)閉Session,保證在視圖顯示層一直打開Session。

這種做法也比較簡單,似乎還不錯,但是副作用卻不容小視。在DAO層數(shù)據(jù)已經(jīng)加載完畢后,數(shù)據(jù)庫Connection在在用戶請求結(jié)束、頁面生成結(jié)束時才關(guān)閉。因而各種原因,如傳輸數(shù)據(jù)大、數(shù)據(jù)傳輸速率低等問題會導致數(shù)據(jù)庫Connection長時間被占用不關(guān)閉,造成連接池不足、網(wǎng)頁訪問慢、網(wǎng)頁假死等現(xiàn)象。

解決方案三:手動初始化數(shù)據(jù)

在關(guān)閉Session之前,初始化代理屬性或者集合屬性。如:

for (Chapters chapter : book.getChapters());

當然這樣代碼可讀性較差,Hibernate也提供了一種方法

Hibernate.initialize(book.getChapters());
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 阿坝县| 沈丘县| 隆林| 壤塘县| 启东市| 铁岭县| 会理县| 德昌县| 施甸县| 久治县| 金山区| 乌拉特中旗| 涞源县| 麟游县| 广昌县| 陇西县| 六盘水市| 宁德市| 股票| 太和县| 岑溪市| 东乡族自治县| 蓬安县| 巴马| 湟中县| 九龙县| 清远市| 鄄城县| 赤壁市| 民丰县| 日土县| 松江区| 潞城市| 汶川县| 额济纳旗| 东平县| 双流县| 夏河县| 甘孜县| 饶平县| 安吉县|