1

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?

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
dimitri
  • 97
  • 2
  • 3
  • 14

3 Answers3

6

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.

Chris
  • 20,138
  • 2
  • 29
  • 43
  • 1
    Isn't it the (implicit) call to the list's toString() method which triggers the lazy-loading? – JB Nizet Dec 14 '11 at 15:17
  • 2
    Also, I find this behavior (of lazy-loading after the transaction has committed) dubious: if the transaction has READ_COMMITTED (or stricter) isolation level, lazy-loading the list after the transaction has ended allows seeing children that didn't exist when the transaction ran, and doesn't show the children that existed when the transaction ran but have been deleted since. You lose the I and the C in ACID. – JB Nizet Dec 14 '11 at 15:21
  • Lazy loading works fine, but on first access to Father entity server executes sql select on Father's Friends. how to stop sql execution on a child entity "SELECT ID, NAME, SURNAME, FATHERID FROM LSDB.dbo.FRIEND WHERE (FATHERID = ?) bind => [3500]" – dimitri Dec 14 '11 at 15:41
  • The SQL should only be issued if the collection is accessed, so if you do not want it brough in, find out how it is being accessed. Common causes are toString methods accessing lazy relationships. As for read_commited and isolation, I do not see the problem with returning the current collection state after the transaction has commited, since if the state prior to the transaction was required, it would have been triggered within the transaction. Most uses cases I've seen want the data now rather than an exception that would force them to reread the parent/child instances. – Chris Dec 14 '11 at 21:49
  • I found if call ejb throw hessian protocol then fields marked as eager filled from database where annotation is @OneToMany. From test servlet jpa executes select query only on requested entity. – dimitri Dec 16 '11 at 12:49
1

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

Community
  • 1
  • 1
CodeShadow
  • 3,503
  • 1
  • 17
  • 16