6 Replies Latest reply on Jun 11, 2009 7:39 AM by Stuart Douglas

    Using Criteria API with Seam app (JPA 1.0)

    Arbi Sookazian Master

      I have a Seam 2.0, JPA 1.0 app.


      I have a use case which allows user to exec dynamic queries (multiple drop-downs, etc).


      I can access the Hibernate Session interface using the following code as per SiA book in my SFSB action method:


      Session session = (Session) entityManager.getDelegate();



      and then exec a query using the Criteria API.  I'm following this excellent article by JSmart: My Link


      So can you still use SMPC with this implementation?  I've never actually needed (until now) to use the Session interface.  Is there any other config or code changes I need to make to accommodate this?

        • 1. Re: Using Criteria API with Seam app (JPA 1.0)
          Jean Luc Apprentice

          I don't see any problems. The PC exposed through the JPA is the same as the Hibernate's one (who is the provider). So, in the end, the same PC ends up being managed by Seam. And the PC is propagated with the transaction (as required by the JPA spec).

          • 2. Re: Using Criteria API with Seam app (JPA 1.0)
            Arbi Sookazian Master

            I'm getting some data (14 rows in the resultset) based on this native query:


            11:41:02,348 INFO  [STDOUT] Hibernate: 
                select
                    this_.RecoveredEquipmentManagementID as Recovere1_1373_1_,
                    this_.AddedDate as AddedDate1373_1_,
                    this_.ICOMS_SITE_ID as ICOMS10_1373_1_,
                    this_.AddedByUserID as AddedBy11_1373_1_,
                    this_.UpdatedByUserID as Updated12_1373_1_,
                    this_.EquipmentType as Equipmen3_1373_1_,
                    this_.ICOMS_ITEM_DESCRIPTION as ICOMS4_1373_1_,
                    this_.ICOMS_ITEM_NONRETURN_CHARGE as ICOMS5_1373_1_,
                    this_.ICOMS_ITEM_NUMBER as ICOMS6_1373_1_,
                    this_.LetterDescription as LetterDe7_1373_1_,
                    this_.RecoveryType as Recovery8_1373_1_,
                    this_.UpdatedDate as UpdatedD9_1373_1_,
                    appsite1_.SiteID as SiteID1392_0_,
                    appsite1_.AddedDate as AddedDate1392_0_,
                    appsite1_.AddedByUserID as AddedByU8_1392_0_,
                    appsite1_.UpdatedByUserID as UpdatedB9_1392_0_,
                    appsite1_.InternalSiteID as Internal3_1392_0_,
                    appsite1_.IsDefaultSite as IsDefaul4_1392_0_,
                    appsite1_.ParentSiteID as ParentSi5_1392_0_,
                    appsite1_.SiteName as SiteName1392_0_,
                    appsite1_.UpdatedDate as UpdatedD7_1392_0_ 
                from
                    EquipmentRecovery.dbo.RecoveredEquipmentManagement this_ 
                inner join
                    EquipmentRecovery.dbo.ApplicationSite appsite1_ 
                        on this_.ICOMS_SITE_ID=appsite1_.SiteID 
                where
                    appsite1_.InternalSiteID=? 
                    and lower(this_.ICOMS_ITEM_NUMBER) like ?



            There are two entities invovled in an inner join for this Criteria query.  Will those entities be managed in the SMPC or is this a projection query?

            • 3. Re: Using Criteria API with Seam app (JPA 1.0)
              Jean Luc Apprentice

              Is the Java code written to treat/convert the results into entities (i.e. the typical case)? If so, yes. Hibenrate will be aware it loaded those entities with their PKs and will cache them in the PC. If the code is not written to treat the results as entities, but as an object array (such as the case when there is a native SQL or an arbitrary selection of fields), then it will not.

              • 4. Re: Using Criteria API with Seam app (JPA 1.0)
                Arbi Sookazian Master

                I don't have the query in front of me but it looks similar to this one from Bauer/King book:


                session.createCriteria(Item.class)
                       .createAlias("bids", "b")
                       .add( Restrictions.like("this.description", "%Foo%") )
                       .add( Restrictions.gt("b.amount", new BigDecimal(100) ) )



                So in this case, I'm assuming that Item entity instances will become managed by the SMPC.

                • 5. Re: Using Criteria API with Seam app (JPA 1.0)
                  Arbi Sookazian Master

                  As a side note, consider this excerpt from JPA w/ Hibernate book:



                  During marshaling of the query results, Hibernate tries to resolve all entity instances by looking them up from the persistence context cache first - it ignores the entity data of the query result if the entity instance is in the persistence context cache.

                  Is this referring to the SMPC (1st level cache) or 2nd level cache?


                  I'm assuming SMPC 1st level cache.  But it seems somewhat counter-intuitive to me.  What if the data in the SMPC cache is stale?  Wouldn't you actually want the fresh entity instances from the query result to not be ignored??

                  • 6. Re: Using Criteria API with Seam app (JPA 1.0)
                    Stuart Douglas Master

                    No, trying to program around the fact the properties of an entity could change every time you issue a query or hibernate lazy load something that requires a DB query would be a nightmare and would create bugs that are impossible to reproduce. You would need to code like the following somewhat contrived example:



                    boolean succesful = false;
                    while(!sucessful)
                    {
                     
                     if(entity.someProperty)
                     {
                       results = em.createQuery("from Entity where someProp=somevalue").getResultList();
                       if(entity.someProperty) //we need to re-test because it may have changed
                       {
                         successful = true;
                       }
                     }
                     else
                     {
                       results = em.createQuery("from Entity where someProp=someOtherValue").getResultList();
                       if(!entity.someProperty) 
                       {
                         successful = true;
                       }
                    
                     }
                    }
                    
                    



                    If you are worried about stale data use versioning timestamps and roll back the transaction when entities are updated behind the scenes.


                    In this case the book is talking about data in the 1st level cache, as far as I am aware hibernate will use query results over data in the second level cache. The second level cache should only be used for loading from primary key.