2011-09-01 48 views
1

我正在運行一個關於Hibernate延遲加載的問題。我在Hibernate Forum上發佈了這個消息,但沒有收到答案,所以我想也許你們在這裏的stackoverflow可以幫助我。該帖子的鏈接是:https://forum.hibernate.org/viewtopic.php?f=1&t=1012419 我在複製下面的內容,提前致謝:正在急切加載的集合,即使lazy = true?

問題是,我試圖懶加載一個集合,但它總是被急切加載,使我的影響巨大應用性能。這裏it's的情況下,我描述了涉及3類模型:

冠軍:有一個聯賽(A冠軍有一個默認的聯賽)。

聯賽:有很多競爭對手 - 屬於一個冠軍(很多聯賽屬於一個總冠軍)。

當我加載錦標賽實體時,相關的聯賽帶有已經加載的競賽隊列表(儘管我的映射文件中有lazy = true)。我粘貼映射文件中的有關部分,這些3個實體:

*************************************************************************************** 
<class name="Championship" table="Championships"> 

<id name="id" type="long" column="id"> 
    <generator class="native" /> 
</id> 
<many-to-one name="defaultLeague" lazy="false" cascade="all" class="League" not-null="true" column="Default_League_FK" unique="true" not-found="ignore"/> 

</class> 

**************************************************************************************** 
<class name="League" table="League"> 

<id name="id" type="long" column="id"> 
    <generator class="native" /> 
</id> 

<many-to-one name="championship" lazy="false" 
class="Championship" column="Championship_FK" /> 

<list name="competitorsList" table="Competitors_League" cascade="all" lazy="true"> 
    <key column="League_FK" not-null="true"/> 
<index column="LeagueIndex" type="long"/> 
<one-to-many class="Competitor" /> 
</list> 

</class> 
***************************************************************************************** 
<class name="Competitor" table="Competitors_League" > 

<key column="id"/> 

<many-to-one name="league" lazy="false" class="League" not-null="true" insert="false" update="false" column="League_FK" /> 

</class> 
****************************************************************************************** 

當我打開一個冠軍實例,錦標賽 - >聯盟 - > competitorsList自帶已裝入所有列表元素。這不應該發生,因爲我有懶=真我的聯賽映射:

<list name=" competitorsList" table="Competitors_League" cascade="all" lazy="true"> 

我已經嘗試了許多不同的方法,我可以得到這個工作,即使看來,我的映射的設置是否正確。

你們能幫我一下嗎?任何幫助將非常感激,因爲我有點卡在這裏。

讓我知道你是否需要任何額外的信息。 謝謝!

評論筆記

注1:集合視圖層(沒有開會議,在視圖過濾器的東西之類的東西在這裏)進行訪問。我應該收到「LazyInitializationException」,這是預期的行爲,而不是集合被急切加載。

注2:我加入類模型,以便給一些額外的語義上下文:

public class League{ 

    private Championship championship; 
     private List<Competitor> competitorsList; 

} 

********************************* 

public class Championship { 

    private League defaultLeague; 
} 
********************************** 

public class Competitor{ 

    private League league; 
} 

注3:Hibernate.isInitialized(league.competitorList)將返回TRUE。取消屬性,但刪除行爲相同。

注4:日誌記錄不顯示集合被提取。我已經設置了DEBUG級別(不能使INFO級別拋出結果),在這裏它是控制檯輸出。

19:14:35,953 DEBUG ErrorCounter:68 - throwQueryException() : no errors 
19:14:35,959 DEBUG HqlSqlBaseWalker:111 - select << begin [level=1, statement=select] 
19:14:35,966 DEBUG FromElement:108 - FromClause{level=1} : com.sportsdt.model.championship (no alias) -> championship0_ 
19:14:35,972 DEBUG FromReferenceNode:51 - Resolved : {synthetic-alias} -> {synthetic-alias} 
19:14:35,979 DEBUG DotNode:569 - getDataType() : enJuego -> [email protected] 
19:14:35,985 DEBUG FromReferenceNode:51 - Resolved : {synthetic-alias}.enJuego -> championship0_.en_juego 
19:14:35,991 DEBUG FromReferenceNode:51 - Resolved : {synthetic-alias} -> {synthetic-alias} 
19:14:35,998 DEBUG DotNode:569 - getDataType() : competencia -> org.hibernate.type.ManyToOneType(com.sportsdt.model.Competencia) 
19:14:36,004 DEBUG DotNode:526 - dereferenceShortcut() : property competencia in com.sportsdt.model.championship does not require a join. 
19:14:36,011 DEBUG DotNode:555 - terminal propertyPath = [competencia] 
19:14:36,017 DEBUG FromReferenceNode:51 - Resolved : {synthetic-alias}.competencia -> championship0_.idCompetencia 
19:14:36,023 DEBUG HqlSqlBaseWalker:117 - select : finishing up [level=1, statement=select] 
19:14:36,030 DEBUG HqlSqlWalker:509 - processQuery() : (SELECT (FromClause{level=1} championships championship0_) (where (and (= (championship0_.en_juego {synthetic-alias} enJuego) ?) (= (championship0_.idCompetencia {synthetic-alias} competencia) ?)))) 
19:14:36,036 DEBUG HqlSqlWalker:716 - Derived SELECT clause created. 
19:14:36,042 DEBUG JoinProcessor:148 - Using FROM fragment [championships championship0_] 
19:14:36,053 DEBUG HqlSqlBaseWalker:123 - select >> end [level=1, statement=select] 
19:14:36,067 DEBUG AST:232 - --- SQL AST --- 
-[SELECT] QueryNode: 'SELECT' querySpaces (championships) 
+-[SELECT_CLAUSE] SelectClause: '{derived select clause}' 
| +-[SELECT_EXPR] SelectExpressionImpl: 'championship0_.id as id29_' {FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=championships,tableAlias=championship0_,origin=null,colums={,className=com.sportsdt.model.championship}}} 
| \-[SQL_TOKEN] SqlFragment: 'championship0_.nombre as nombre29_, championship0_.cantidadFechas as cantidad3_29_, championship0_.fecha_inicio as fecha4_29_, championship0_.fecha_fin as fecha5_29_, championship0_.en_juego as en6_29_, championship0_.idCompetencia as idCompet7_29_, championship0_.disponible_penca as disponible8_29_, championship0_.disponible_entrenador as disponible9_29_, championship0_.League_General_FK as League10_29_' 
+-[FROM] FromClause: 'from' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[], fromElementByTableAlias=[championship0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]} 
| \-[FROM_FRAGMENT] FromElement: 'championships championship0_' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=championships,tableAlias=championship0_,origin=null,colums={,className=com.sportsdt.model.championship}} 
\-[WHERE] SqlNode: 'where' 
    \-[AND] SqlNode: 'and' 
     +-[EQ] BinaryLogicOperatorNode: '=' 
     | +-[DOT] DotNode: 'championship0_.en_juego' {propertyName=enJuego,dereferenceType=4,propertyPath=enJuego,path={synthetic-alias}.enJuego,tableAlias=championship0_,className=com.sportsdt.model.championship,classAlias=null} 
     | | +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}} 
     | | \-[IDENT] IdentNode: 'enJuego' {originalText=enJuego} 
     | \-[PARAM] ParameterNode: '?' {ordinal=0, [email protected]} 
     \-[EQ] BinaryLogicOperatorNode: '=' 
     +-[DOT] DotNode: 'championship0_.idCompetencia' {propertyName=competencia,dereferenceType=ROOT_LEVEL,propertyPath=competencia,path={synthetic-alias}.competencia,tableAlias=championship0_,className=com.sportsdt.model.championship,classAlias=null} 
     | +-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}} 
     | \-[IDENT] IdentNode: 'competencia' {originalText=competencia} 
     \-[PARAM] ParameterNode: '?' {ordinal=1, expectedType=org.hibernate.type.ManyToOneType(com.sportsdt.model.Competencia)} 

19:14:36,074 DEBUG ErrorCounter:68 - throwQueryException() : no errors 
19:14:36,080 DEBUG QueryTranslatorImpl:216 - HQL: from com.sportsdt.model.championship where enJuego=? and competencia=? 
19:14:36,086 DEBUG QueryTranslatorImpl:217 - SQL: select championship0_.id as id29_, championship0_.nombre as nombre29_, championship0_.cantidadFechas as cantidad3_29_, championship0_.fecha_inicio as fecha4_29_, championship0_.fecha_fin as fecha5_29_, championship0_.en_juego as en6_29_, championship0_.idCompetencia as idCompet7_29_, championship0_.disponible_penca as disponible8_29_, championship0_.disponible_entrenador as disponible9_29_, championship0_.League_General_FK as League10_29_ from championships championship0_ where championship0_.en_juego=? and championship0_.idCompetencia=? 
19:14:36,092 DEBUG ErrorCounter:68 - throwQueryException() : no errors 
19:14:54,360 DEBUG JDBCTransaction:103 - commit 
19:14:57,136 DEBUG JDBCTransaction:193 - re-enabling autocommit 
19:14:57,141 DEBUG JDBCTransaction:116 - committed JDBC Connection 

如果我設置log4j.logger.org.hibernate.SQL =調試它顯示的選擇大量的(如it's預期),而這些操作包括選擇,並加入對錶,但我看到這種亂七八糟的信息是沒用的。

回答

0

從未使用基於xml的實體描述,但下面的鏈接可能對您有用。

http://java.sun.com/javaee/6/docs/api/javax/persistence/FetchType.html

定義從數據庫中提取數據的策略。 EAGER 策略是持久性提供程序運行時的一項要求,必須急於提取數據 。 懶惰策略是提示到 持久性提供程序運行時,數據應在第一次訪問 時緩慢提取。 允許實現熱切地獲取 已爲其指定了LAZY策略提示的數據

另一個問題是你如何確定競爭對手是急於加載。例如,任何對getCompetitorsList().size()的調用都將導致列表被加載。如果不是這種情況,你應該尋找可以保證延遲加載的特定於hibernate的配置選項。

+0

感謝您的答覆,我使用普通的休眠,不JPA和懶惰的策略設置。關於第二個問題,我更新了包含該信息的帖子。 – Distortion

0

您正在使用一對一關聯。別。你的使用意味着聯賽和冠軍擁有相同的主鍵。

多到一個正確的倒數是「設置」

我不能告訴從你的描述的元數。但是,如果一個聯賽中有一個單一的冠軍,隨後在聯賽,你應該有:

<set name="allChampions" access="field" 
     cascade="all-delete-orphan" lazy="true"> 
     <key column="league" not-null="true"/> 
     <one-to-many class="Championship"/> 
    </set> 

同樣你的競爭對手「清單」或許應該是一組,除非你有訂購競爭對手的理由。

btw什麼與類名稱開頭的所有空格?

更新:

  1. 你怎麼知道的名單正在急切地獲取?我會建議打開SQL日誌記錄,以確保調試不會導致問題。
  2. 刪除提取屬性。獲取影響加載並對加載產生副作用。

使用org.hibernate.Hibernate.isInitialized(league.competitorList)來確定列表是否真正被初始化。

此的log4j.xml片段將與記錄有助於確定什麼時候收集是牽強:

<logger name="org.hibernate"> 
     <level value="INFO"/> 
    </logger> 
    <!-- log HQL query parser activity --> 
    <logger name="org.hibernate.hql.ast.AST"> 
     <level value="INFO"/> 
    </logger> 
    <!-- log just the SQL --> 
    <logger name="org.hibernate.SQL"> 
     <level value="INFO"/> 
    </logger> 
    <!-- log JDBC bind parameters  --> 
    <logger name="org.hibernate.type"> 
     <level value="INFO"/> 
    </logger> 

    <!-- log schema export/update --> 
    <logger name="org.hibernate.tool.hbm2ddl"> 
     <level value="INFO"/> 
    </logger> 

    <!-- log HQL parse trees --> 
    <logger name="org.hibernate.hql"> 
     <level value="INFO"/> 
    </logger> 
    <!-- log cache activity --> 
    <logger name="org.hibernate.cache"> 
     <level value="INFO"/> 
    </logger> 
    <!-- log transaction activity (TRACE for very detailed) --> 
    <logger name="org.hibernate.transaction"> 
     <level value="INFO"/> 
    </logger> 
    <!-- log JDBC resource acquisition --> 
    <logger name="org.hibernate.jdbc"> 
     <level value="INFO"/> 
    </logger> 
+0

爲了在這裏帶來一些語義,我添加了類模型。其實我正在使用unique = true的多對一​​,如下所述:http://docs.jboss.org/hibernate/core/3.5/reference/en/html/associations.html#assoc-unidirectional-121。聯賽冠軍協會不是雙向的,冠軍賽有一個默認聯賽(從冠軍到聯賽唯一的多對一),作爲一個單獨的聯賽屬於冠軍<多對一名稱=「冠軍」lazy = 「false」fetch =「join」class =「Championship」column =「Championship_FK」/>(一對一是一個錯誤,我編輯過) – Distortion

+0

請參閱我在Notes 3和4上的更新。謝謝! – Distortion