LazyInitializationException的四种解决方案–第2部分
使用PersistenceContextType.EXTENDED的有狀態(tài)EJB加載收集
該方法只能應(yīng)用于與Full JEE環(huán)境兼容的應(yīng)用程序:將EJB與PersistenceContextType.EXTENDED一起使用。
檢查下面的代碼,DAO的樣子:
package com.ejb;import javax.ejb.Stateful; import javax.persistence.*;import com.model.Person;@Stateful public class SystemDAOStateful {@PersistenceContext(unitName = 'LazyPU', type=PersistenceContextType.EXTENDED)private EntityManager entityManager;public Person findByName(String name) {Query query = entityManager.createQuery('select p from Person p where name = :name');query.setParameter('name', name);Person result = null;try {result = (Person) query.getSingleResult();} catch (NoResultException e) {// no result found}return result;} }public class DataMB {// other methods and attributes@EJBprivate SystemDAOStateful daoStateful;public Person getPersonByStatefulEJB() {return daoStateful.findByName('Mark M.');} }<h:dataTable var='dog' value='#{dataMB.personByStatefulEJB.lazyDogs}'><h:column><f:facet name='header'>Dog name</f:facet>#{dog.name}</h:column> </h:dataTable>這種方法的優(yōu)點和缺點:
優(yōu)點 | 缺點 |
容器將控制數(shù)據(jù)庫事務(wù) | 僅適用于JEE |
模型類別將不需要編輯 | 可能會發(fā)生N + 1效應(yīng) |
大量的有狀態(tài)EJB可能會影響容器內(nèi)存。 |
這種方法可能會產(chǎn)生N + 1效果,并且有狀態(tài)EJB的特征是在其會話未到期或丟失參考之前不會被刪除/銷毀。
警告 :在保留在Pool中的對象中保留對注入的EJB的引用不是一個好習(xí)慣。 JSF將創(chuàng)建一個ManagedBean池以更好地處理用戶請求。 必要時,容器將增加或減少池中ManagedBean的數(shù)量。 在本文的代碼中,假設(shè)如果容器在池中創(chuàng)建100個ManagedBeans實例,則服務(wù)器將在內(nèi)存中容納100個有狀態(tài)EJB。 解決該問題的方法是對有狀態(tài)EJB進行JNDI查找。
通過聯(lián)接查詢加載集合
該解決方案易于理解和應(yīng)用。
請參見下面的代碼:
public Person findByNameWithJoinFech(String name) {Query query = entityManager.createQuery('select p from Person p join fetch p.lazyDogs where p.name = :name');query.setParameter('name', name);Person result = null;try {result = (Person) query.getSingleResult();} catch (NoResultException e) {// no result found}return result;}public Person getPersonByQuery() {return systemDAO.findByNameWithJoinFech('Mark M.');}<h:dataTable var='dog' value='#{dataMB.personByQuery.lazyDogs}'><h:column><f:facet name='header'>Dog name</f:facet>#{dog.name}</h:column></h:dataTable>這種方法的優(yōu)點和缺點:
優(yōu)點 | 缺點 |
數(shù)據(jù)庫中只會觸發(fā)一個查詢 | 每個訪問的集合/惰性屬性都需要一個查詢 |
模型類別將不需要編輯 | |
將只帶來所需的數(shù)據(jù) | |
N + 1效果不會發(fā)生 |
這種方法的缺點是需要新的查詢來訪問每個模型類集合/惰性屬性。 如果只需要查詢“ Person”狗,則需要特定查詢。 假設(shè)我們需要查詢“個人”電子郵件,則有必要進行其他查詢。
這種方法可以應(yīng)用于JSE和JEE。
EclipseLink和惰性集合初始化
關(guān)系的默認值為:
關(guān)系 | 取 |
@OneToOne | 急于 |
@OneToMany | 懶 |
@多多 | 急于 |
@多多多 | 懶 |
但是JPA Spec *指出:
EAGER策略是對持久性提供程序運行時的要求,必須熱切地獲取數(shù)據(jù)。 LAZY策略向持久性提供程序運行時提供了提示,即首次訪問數(shù)據(jù)時應(yīng)延遲獲取數(shù)據(jù)。 該實現(xiàn)允許急切地獲取已為其指定LAZY策略提示的數(shù)據(jù) 。 特別是,懶惰獲取可能僅適用于使用基于屬性的訪問的基本映射。
如您在上面的文本中看到的那樣,JPA實現(xiàn)可能會忽略提示策略。 EclipseLink具有JEE行為和JSE其他行為。 您可以在此處查看每種行為: http : //wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#What_You_May_Need_to_Know_About_EclipseLink_JPA_Lazy_Loading
我們可以在互聯(lián)網(wǎng)上找到一些人說,即使是惰性集合,EclipseLink也會在加載實體時執(zhí)行n + 1查詢。 我們可以找到使用Glassfish和EJB的用戶的這種行為。
在下面,您將看到一些在EclipseLink上正確使用延遲加載的提示:
- http://stackoverflow.com/questions/8490532/eclipselink-lazy-loading
- http://stackoverflow.com/questions/3932623/eclipselink-dont-fetch-some-fields-by-default
- https://forums.oracle.com/forums/thread.jspa?messageID=1706796
* JSR-000220企業(yè)JavaBeans 3.0最終版本(持久性)9.1.18,并將重復(fù)與水獺JPA的關(guān)系。
結(jié)束!
我認為最好的解決方案是聯(lián)接獲取查詢。 您可以根據(jù)自己的應(yīng)用選擇最佳解決方案 。
單擊此處下載此帖子的源代碼 。 如果要運行本文的代碼,則需要創(chuàng)建一個名為LazyExceptionDB的數(shù)據(jù)庫和JBoss模塊。 附加到源代碼的是Postgres模塊。 如果您想了解如何設(shè)置數(shù)據(jù)源以及Postgres或MySQL模塊,則可以在這里查看: 完整的WebApplication JSF EJB JPA JAAS 。
希望這篇文章對您有所幫助。
如果您有任何意見或疑問,請發(fā)表。
再見。
參考: uaiHebert博客上的JCG合作伙伴 Hebert Coelho 對LazyInitializationException的四個解決方案 。
翻譯自: https://www.javacodegeeks.com/2012/07/four-solutions-to-lazyinitializationexc.html
總結(jié)
以上是生活随笔為你收集整理的LazyInitializationException的四种解决方案–第2部分的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一忘皆空什么意思 一忘皆空的解释
- 下一篇: 接触Jenkins(Hudson)API