Why doesn't JPA's FetchType.LAZY work?

爷,独闯天下 提交于 2019-12-23 01:52:07

问题


JPA provider eclipselink 2.3 AS glassfish 3.1.1 B12 Binary protocol for remote invocation Hessian

Server side ejb+jpa Client side Plain Swing .

JPA mappings

@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 Method

   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;
    }

Client Side Call over Hessian

   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) {

  }

 }

everything works fine, but when view server log and Father entity related parties I discovered that LazyLoaded anotated fields is filled from database.

Server Log

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] : [com.sun.enterprise.v3.admin.DynamicInterceptor@266bad10].
FINER: JMX MBeanServer instance found: [com.sun.enterprise.v3.admin.DynamicInterceptor@266bad10], # of beans: [21], domain: [DefaultDomain] at index: [0].
WARNING: JMX MBeanServer in use: [com.sun.enterprise.v3.admin.DynamicInterceptor@266bad10] from index [0] 
FINER: JMX MBeanServer instance found: [com.sun.jmx.mbeanserver.JmxMBeanServer@6f7adf19], # of beans: [24], domain: [DefaultDomain] at index: [1].
WARNING: JMX MBeanServer in use: [com.sun.jmx.mbeanserver.JmxMBeanServer@6f7adf19] 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 com.sun.jmx.mbeanserver.JmxMBeanServer@6f7adf19
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 com.sun.jmx.mbeanserver.JmxMBeanServer@6f7adf19
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 ]

Why JPA provider executes this SELECT ID, NAME, SURNAME, FATHERID FROM LSDB.dbo.FRIEND WHERE (FATHERID = ?) bind => [3500]

Any idea?


回答1:


Lazy loading is only done for xToMany relation in a Java SE environment by default (since EclipseLink can use IndirectList where collections are used). If you want to lazy load xToOne relations you have to use class weaving.




回答2:


Lazy fetch type is working. Lazy relationships allow delaying the fetching of the referenced entities until they are first accessed, which seems to be happenging when you call father.getFriendList(). If it were not working, this call would do nothing and the relationship fetched immediately when the father was read in.

EclipseLink allows accessing a lazy relationship as long as the connection is still available as described here: http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg05258.html If you serialize the entity you will get the exception as the context to read in the relationship will not be available.

If you wish an exception be thrown instead when you access a lazy relationship on a detached but not serialized entity, please file an enhancement request in EclipseLink.




回答3:


The EAGER strategy is a requirement on the persistence provider runtime that the value must be eagerly fetched. The LAZY strategy is a hint to the persistence provider runtime.

Found this answer here. JPA fetchType.Lazy is not working

One more thing: JPA uses weaving to accomplish this. wiki-eclipse



来源:https://stackoverflow.com/questions/8505854/why-doesnt-jpas-fetchtype-lazy-work

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!