2011-12-14 138 views
1

JPA提供商遠程調用的Hessian爲什麼JPA的FetchType.LAZY不起作用?

服務器側EJB + JPA 客戶端側平原搖擺的EclipseLink 2.3 AS的glassfish 3.1.1 B12 二進制協議。

JPA映射

@Entity 
@Table(name = "FATHER", catalog = "CAT", schema = "dbo") 
public class Father implements Serializable { 

    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(generator = "FATHERUID", strategy = GenerationType.TABLE) 
    @TableGenerator(name = "FATHERUID", table = "FAMILY_UID", catalog = "LSDB", schema = "dbo", pkColumnName = "PRIM", pkColumnValue = "father_uid", valueColumnName = "UID", allocationSize = 1, initialValue = 0) 
    private Long id; 

    @OneToOne(mappedBy = "father", fetch = FetchType.LAZY) 
    private Mother mother; 

    @OneToMany(mappedBy = "father", fetch = FetchType.LAZY) 
    private List<Friend> friendList; 

} 


@Entity 
@Table(name = "FRIEND", catalog = "CAT", schema = "dbo") 
@NamedQueries({ 
    @NamedQuery(name = "Friend.findAll", query = "SELECT f FROM Friend f")}) 
public class Friend implements Serializable { 

    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(generator = "FRIENDUID", strategy = GenerationType.TABLE) 
    @TableGenerator(name = "FRIENDUID", table = "FAMILY_UID", catalog = "LSDB", schema = "dbo", pkColumnName = "PRIM", pkColumnValue = "friend_uid", valueColumnName = "UID", allocationSize = 1, initialValue = 0) 
    private Long id; 

    @JoinColumn(name = "FATHERID", referencedColumnName = "ID") 
    @ManyToOne(optional = false,fetch= FetchType.LAZY) 
    private Father father; 

} 

EJB方法

public Father findFather(long id) { 

     Father fath = em.find(Father.class, id); 

     PersistenceUnitUtil util = em.getEntityManagerFactory().getPersistenceUnitUtil(); 

     System.out.println("mother isloaded="+util.isLoaded(fath,"mother")); 
     System.out.println("friendList isloaded="+util.isLoaded(fath,"friendList")); 

     return fath; 
    } 

客戶端調用了黑森州

public void findFather() { 

     try { 

     IManager manager = ProxyHelper.getStub(); 
     //find by father id 
     Father father = manager.findFather(3500L); 

     System.out.println("Father=" + father); 
     System.out.println("father's friends=" + father.getFriendList()); 
     System.out.println("mother=" + father.getMother()); 

    } catch (MalformedURLException ex) { 

    } 

} 

一切工作正常,但是當查看服務器日誌和Father實體相關方時,我發現 LazyLoaded anotated字段是從數據庫中填充的。

服務器日誌

FINEST: Begin deploying Persistence Unit test; session file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test; state Predeployed; factoryCount 1 
INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver. 
FINEST: property=eclipselink.target-server; value=SunAS9; translated value=org.eclipse.persistence.platform.server.sunas.SunAS9ServerPlatform 
FINEST: property=eclipselink.logging.level; value=FINEST; translated value=FINEST 
FINEST: property=eclipselink.logging.parameters; value=true 
FINEST: property=eclipselink.logging.level; value=FINEST; translated value=FINEST 
FINEST: property=eclipselink.logging.parameters; value=true 
FINEST: property=eclipselink.cache.shared.default; value=false; translated value=false 
INFO: EclipseLink, version: Eclipse Persistence Services - 2.3.2.v20111125-r10461 
FINEST: Database platform: org.eclipse.persistence.platform.database.oracle.Oracle11Platform, regular expression: (?i)oracle.*11 
FINEST: Database platform: org.eclipse.persistence.platform.database.oracle.Oracle10Platform, regular expression: (?i)oracle.*10 
FINEST: Database platform: org.eclipse.persistence.platform.database.oracle.Oracle9Platform, regular expression: (?i)oracle.*9 
FINEST: Database platform: org.eclipse.persistence.platform.database.oracle.OraclePlatform, regular expression: (?i)oracle.* 
FINEST: Database platform: org.eclipse.persistence.platform.database.SQLAnywherePlatform, regular expression: SQL\ Anywhere.* 
FINEST: Database platform: org.eclipse.persistence.platform.database.SybasePlatform, regular expression: (?i)(sybase.*)|(adaptive\ server\ enterprise.*)|(SQL\ Server.*) 
FINEST: Database platform: org.eclipse.persistence.platform.database.SQLServerPlatform, regular expression: (?i)microsoft.* 
FINE: Detected database platform: org.eclipse.persistence.platform.database.SQLServerPlatform 
CONFIG: connecting(DatabaseLogin(
    platform=>DatabasePlatform 
    user name=> "" 
    connector=>JNDIConnector datasource name=>null 
)) 
CONFIG: Connected: jdbc:jtds:sqlserver: 
    User: user 
    Database: Microsoft SQL Server Version: 10.50.1600 
    Driver: jTDS Type 4 JDBC Driver for MS SQL Server and Sybase Version: 1.2.5 
FINEST: Connection acquired from connection pool [read]. 
FINEST: Connection released to connection pool [read]. 
CONFIG: connecting(DatabaseLogin(
    platform=>SQLServerPlatform 
    user name=> "" 
    connector=>JNDIConnector datasource name=>null 
)) 
CONFIG: Connected: jdbc:jtds:sqlserver: 
    User: user 
    Database: Microsoft SQL Server Version: 10.50.1600 
    Driver: jTDS Type 4 JDBC Driver for MS SQL Server and Sybase Version: 1.2.5 
FINEST: sequencing connected, state is Preallocation_Transaction_NoAccessor_State 
FINEST: sequence child_uid: preallocation size 1 
FINEST: sequence friend_uid: preallocation size 1 
FINEST: sequence father_uid: preallocation size 1 
FINEST: sequence mother_uid: preallocation size 1 
INFO: file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test login successful 
WARNING: Multiple [2] JMX MBeanServer instances exist, we will use the server at index [0] : [[email protected]]. 
FINER: JMX MBeanServer instance found: [[email protected]], # of beans: [21], domain: [DefaultDomain] at index: [0]. 
WARNING: JMX MBeanServer in use: [[email protected]] from index [0] 
FINER: JMX MBeanServer instance found: [[email protected]], # of beans: [24], domain: [DefaultDomain] at index: [1]. 
WARNING: JMX MBeanServer in use: [[email protected]] from index [1] 
FINEST: Registered MBean: org.eclipse.persistence.services.mbean.MBeanDevelopmentServices[TopLink:Name=Development-file_/C_/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test,Type=Configuration] on server [email protected] 
FINEST: Registered MBean: org.eclipse.persistence.services.glassfish.MBeanGlassfishRuntimeServices[TopLink:Name=Session(file_/C_/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test)] on server [email protected] 
FINEST: EclipseLink JMX Runtime Services is referencing the [Platform ConversionManager] ClassLoader at: [WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)] 
FINEST: The applicationName for the MBean attached to session [file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test] is [unknown] 
FINEST: The moduleName for the MBean attached to session [file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test] is [unknown] 
FINER: Canonical Metamodel class [org.dima.model.Child_] not found during initialization. 
FINER: Canonical Metamodel class [org.dima.model.Friend_] not found during initialization. 
FINER: Canonical Metamodel class [org.dima.model.Father_] not found during initialization. 
FINER: Canonical Metamodel class [org.dima.model.Mother_] not found during initialization. 
FINEST: End deploying Persistence Unit test; session file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test; state Deployed; factoryCount 1 
FINER: client acquired: 50658177 
FINER: TX binding to tx mgr, status=STATUS_ACTIVE 
FINER: acquire unit of work: 1008456627 
FINEST: Execute query ReadObjectQuery(name="readObject" referenceClass=Father sql="SELECT ID, NAME, SURNAME FROM LSDB.dbo.FATHER WHERE (ID = ?)") 
FINEST: Connection acquired from connection pool [read]. 
FINEST: reconnecting to external connection pool 
FINE: SELECT ID, NAME, SURNAME FROM LSDB.dbo.FATHER WHERE (ID = ?) 
    bind => [3500] 
FINEST: Connection released to connection pool [read]. 
INFO: mother isloaded=false 
INFO: friendList isloaded=false 
FINER: TX beforeCompletion callback, status=STATUS_ACTIVE 
FINER: begin unit of work commit 
FINER: TX afterCompletion callback, status=COMMITTED 
FINER: end unit of work commit 
FINER: release unit of work 
FINER: client released 
FINEST: Execute query ReadAllQuery(name="file:/C:/netbeans/projects/JPATestServer/build/web/WEB-INF/classes/_test" referenceClass=Friend) 
FINEST: Connection acquired from connection pool [read]. 
FINEST: reconnecting to external connection pool 
**FINE: SELECT ID, NAME, SURNAME, FATHERID FROM LSDB.dbo.FRIEND WHERE (FATHERID = ?) 
    bind => [3500]** 
FINEST: Connection released to connection pool [read]. 
FINEST: Register the existing object org.dima.model.Friend[ id=17496 ] 
FINEST: Register the existing object org.dima.model.Friend[ id=17497 ] 
FINEST: Register the existing object org.dima.model.Friend[ id=17498 ] 
FINEST: Register the existing object org.dima.model.Friend[ id=17499 ] 
FINEST: Register the existing object org.dima.model.Friend[ id=17500 ] 

爲什麼JPA提供商執行該 SELECT ID,名字,姓氏,FATHERID FROM LSDB.dbo.FRIEND WHERE(FATHERID =?) 綁定=> [3500]

有什麼想法?

回答

2

懶惰獲取類型正在工作。延遲關係允許延遲引用實體的讀取,直到它們第一次被訪問,這在您調用father.getFriendList()時似乎正在發生。如果它沒有工作,這個調用將不會執行任何操作,當父親被讀入時,該關係立即被取回。

只要連接仍然可用,EclipseLink就允許訪問惰性關係,如下所述:http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg05258.html如果您序列化實體你將得到異常,因爲在關係中讀取的上下文將不可用。

如果希望在分離但未序列化的實體上訪問惰性關係時拋出異常,請在EclipseLink中提交增強請求。

+1

是不是(觸發)列表的toString()方法觸發延遲加載的(隱式)調用? – 2011-12-14 15:17:01

+2

另外,我發現這種行爲(事務提交後的延遲加載)可疑:如果事務具有READ_COMMITTED(或更嚴格)隔離級別,則在事務結束後延遲加載列表允許查看不存在的子項當事務運行時,並且不顯示事務運行但已被刪除的子項。你在ACID中失去了I和C. – 2011-12-14 15:21:24

5

默認情況下,僅在Java SE環境中爲xToMany關係執行延遲加載(因爲EclipseLink可以使用使用IndirectList的集合)。如果你想延遲加載xToOne關係,你必須使用類編織。

0

EAGER策略是對持久性提供 運行時,該值必須預先抓取一個要求LAZY策略是 提示到持久性提供程序運行時。

在這裏找到了答案。 JPA fetchType.Lazy is not working

還有一件事:JPA使用編織來完成此操作。wiki-eclipse