glassfish
  1. glassfish
  2. GLASSFISH-3328

ManyToMany relationship marked as FetchType.LAZY get touched during backup clone building

    Details

    • Issuezilla Id:
      3,328

      Description

      I have an entity called Thing with a List-property called labels mapped as @ManyToMany(fetch=FetchType.LAZY). When I query for this object through
      EJBQL, as in "select t from Thing t", the object building code seems to hit getLabels, and fetches the relationship eagerly, kind of defeating the purpose of
      marking it as LAZY in the first place.

      I, for debugging sake, put a stack-trace dump in the getter which seems to denote that it is the backup cloning that touches the getter:

      com.maketechnologies.tlm.semanticator.objectmodel.Thing.getLabels(Thing.java:156)
      at sun.reflect.GeneratedMethodAccessor71.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:585)
      at oracle.toplink.essentials.internal.security.PrivilegedAccessHelper.invokeMethod(PrivilegedAccessHelper.java:307)
      at oracle.toplink.essentials.internal.descriptors.MethodAttributeAccessor.getAttributeValueFromObject(MethodAttributeAccessor.java:76)
      at oracle.toplink.essentials.mappings.DatabaseMapping.getAttributeValueFromObject(DatabaseMapping.java:357)
      at oracle.toplink.essentials.mappings.ForeignReferenceMapping.getAttributeValueFromObject(ForeignReferenceMapping.java:317)
      at oracle.toplink.essentials.mappings.ForeignReferenceMapping.buildBackupClone(ForeignReferenceMapping.java:99)
      at oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildBackupClone(ObjectBuilder.java:302)
      at oracle.toplink.essentials.descriptors.changetracking.DeferredChangeDetectionPolicy.buildBackupClone(DeferredChangeDetectionPolicy.java:163)
      at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.populateAndRegisterObject(UnitOfWorkImpl.java:2837)
      at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:673)
      at oracle.toplink.essentials.internal.sessions.UnitOfWorkIdentityMapAccessor.getAndCloneCacheKeyFromParent(UnitOfWorkIdentityMapAccessor.java:152)
      at oracle.toplink.essentials.internal.sessions.UnitOfWorkIdentityMapAccessor.getFromIdentityMap(UnitOfWorkIdentityMapAccessor.java:90)
      at oracle.toplink.essentials.internal.sessions.IdentityMapAccessor.getFromIdentityMap(IdentityMapAccessor.java:295)
      at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3075)
      at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3024)
      at oracle.toplink.essentials.queryframework.ObjectBuildingQuery.registerIndividualResult(ObjectBuildingQuery.java:319)
      at oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildWorkingCopyCloneNormally(ObjectBuilder.java:441)
      at oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildObjectInUnitOfWork(ObjectBuilder.java:406)
      at oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:372)
      at oracle.toplink.essentials.queryframework.ReportQueryResult.processItem(ReportQueryResult.java:205)
      at oracle.toplink.essentials.queryframework.ReportQueryResult.buildResult(ReportQueryResult.java:167)
      at oracle.toplink.essentials.queryframework.ReportQueryResult.<init>(ReportQueryResult.java:83)
      at oracle.toplink.essentials.queryframework.ReportQuery.buildObject(ReportQuery.java:579)
      at oracle.toplink.essentials.queryframework.ReportQuery.buildObjects(ReportQuery.java:628)
      at oracle.toplink.essentials.queryframework.ReportQuery.executeDatabaseQuery(ReportQuery.java:776)
      at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:609)
      at oracle.toplink.essentials.queryframework.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:677)
      at oracle.toplink.essentials.queryframework.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:731)
      at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2219)
      at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:937)
      at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:909)
      at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:346)
      at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.getResultList(EJBQueryImpl.java:453)
      at com.maketechnologies.tlm.semanticator.web.base.search.SearchBackingBean.fetch(SearchBackingBean.java:142)

        Activity

        Hide
        miklernout added a comment -

        It is probably best to close this issue. We have decided to switch to the Hibernate implementation of EJB 3
        in the short term as we need to get something working

        I will probably not have time to create a test case which isolates this bug. I'd like to note though that the
        SQL backing the lazy List is being triggered and that getMethod() is done by Toplink, not by our
        application code, we are just querying as you can see in the stacktrace.

        Show
        miklernout added a comment - It is probably best to close this issue. We have decided to switch to the Hibernate implementation of EJB 3 in the short term as we need to get something working I will probably not have time to create a test case which isolates this bug. I'd like to note though that the SQL backing the lazy List is being triggered and that getMethod() is done by Toplink, not by our application code, we are just querying as you can see in the stacktrace.
        Hide
        gyorke added a comment -

        To be clear a call to
        com.maketechnologies.tlm.semanticator.objectmodel.Thing.getLabels() should not
        be causing SQL to be fired, only method calls on the underlying collection will
        cause SQL. Can you provide the source to Thing.java ? or at least the source
        to the getLabels() method?

        Show
        gyorke added a comment - To be clear a call to com.maketechnologies.tlm.semanticator.objectmodel.Thing.getLabels() should not be causing SQL to be fired, only method calls on the underlying collection will cause SQL. Can you provide the source to Thing.java ? or at least the source to the getLabels() method?
        Hide
        miklernout added a comment -

        I should have been more clear there: getLabels contains:

        public List<Label> getLabels()

        { new Exception().printStacktrace(); return labels; }

        I put the stack trace there just to see who was calling the getter in the first place. I agree that it is not that
        act in itself which is forcing the SQL to be run, but it is running and the code pointed out is the only thing
        hitting that getter. So I assume it has something to do with it...

        Show
        miklernout added a comment - I should have been more clear there: getLabels contains: public List<Label> getLabels() { new Exception().printStacktrace(); return labels; } I put the stack trace there just to see who was calling the getter in the first place. I agree that it is not that act in itself which is forcing the SQL to be run, but it is running and the code pointed out is the only thing hitting that getter. So I assume it has something to do with it...
        Hide
        gyorke added a comment -

        I think this method call is a bit of a red herring. Try adding a PostLoad
        method on the Label class. This will get triggered when the lazy relationship
        loads the lables.

        @PostLoad
        protected void trackLoading()

        { System.out.println(" ********* DEBUG ********** loading Label"); new Exception().printStackTrace(); }
        Show
        gyorke added a comment - I think this method call is a bit of a red herring. Try adding a PostLoad method on the Label class. This will get triggered when the lazy relationship loads the lables. @PostLoad protected void trackLoading() { System.out.println(" ********* DEBUG ********** loading Label"); new Exception().printStackTrace(); }
        Hide
        pkrogh added a comment -

        I can't reproduce this. I think there is something in the configuration of the
        app.

        Show
        pkrogh added a comment - I can't reproduce this. I think there is something in the configuration of the app.

          People

          • Assignee:
            tware
            Reporter:
            miklernout
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: