persistence@glassfish.java.net

RE: Disable TopLink caching

From: Gordon Yorke <gordon.yorke_at_oracle.com>
Date: Thu, 31 Aug 2006 09:36:58 -0400

Hello Wonseok,
    That's correct NONE should not be used to eliminate all caching. The WEAK option is not exposed to the infinite recursion issue as an identity map exists that allows TopLink to maintain object identity and not build objects multiple times.

    It has just come to my attention that we have exposed additional TopLink functionality through configuration properties toplink.cache.shared.<ENTITY> = boolean . By setting this property to false TopLink will not share the objects between Entity Managers. Although it is not a direct cache type setting it will most likely give you what you are looking for, no caching between EntityManagers. This property is available on a per entity basis and different entities in the same PU can have different values having some shared for performance reasons. There is an additional property that will set this property for all entities in a PU but there seems to be an issue with it currently.

    I would like to point out that eliminating caching will have performance implications and in most cases is beyond what the user really needs.

--Gordon
  -----Original Message-----
  From: Wonseok Kim [mailto:guruwons_at_gmail.com]
  Sent: Thursday, August 31, 2006 12:15 AM
  To: persistence_at_glassfish.dev.java.net
  Subject: Re: Disable TopLink caching


  Thanks, Gordon!
  Reply in line...


  On 8/30/06, Gordon Yorke <gordon.yorke_at_oracle.com> wrote:
    Wonseok, what does your commitAndClose() method do? Is it closing the EntityManager? The same update performed through the EntityManager would have the correct results. If an application needs to guarantee that it has the latest data then the object must be refreshed. In practice applications do not want to avoid caching. There may be some limited use cases that require direct database access but these can be handled with special queries or refreshing. As soon as data is read it is already stale.

    Having said that...


  In my previous sample code, commitAndClose() did commit EntityTransaction and close EntityManager to ensure that EntityManager(client session in TopLink) is not shared.
  The code tried to simulate transaction-scoped persistence context used normally in Java EE environment.


    When the WEAK option is set TopLink does not actively cache any objects. When the Object is no longer used in the application it is up for garbage collection and will be removed. While the object remains within the VM, most likely because it is still being referenced, other reading threads will find that same object but TopLink will not have that object in memory any longer than the garbage collector allows. This ensures efficiently built object trees. In practice this provides applications with no caching. With the other caching options TopLink maintains a cache of MRU objects, these caches exists for the life of the application.


  Anyway you explanation clarified the situation. With Weak option TopLink does cache(not actively but it does) until GC. To ensure to get fresh data in this situation, refresh() or " toplink.refresh" query hint should be used. Also NONE option should not be used to get this behaviour. Right?



    The NONE option is misleading. It means a lot more than just no caching it also means there is no referential integrity when building the objects. This setting is an advanced performance optimization for those cases when the User informs TopLink that TopLink need not maintain referential integrity for what ever reason. This setting can result in infinite recursion if there is a cycle of eagerly loaded relationships. This option should not really be documented with the other options.


   If NONE option can cause infinite recursion if there is a cycle of eagerly loaded relationships, how about Weak option in that case if there is no cached entities at all (after GC)? Does Weak option never cause such infinite recursion? Or just the possibility of such case is less than NONE?



    If there is demand for a setting that guarantees each and every query will go to the database then a feature request should be added to expose this functionality through JPA to have TopLink always refresh the data for users.


  What I tried to do is getting fresh one from database when I read data first time after transaction begin. So I'm not saying an option that every find() or SELECT query do refresh. I don't know there is a demand for the behaviour. IMO, the behaviour seems undesirable because it can change the content of managed entities inside of persistence context unexpectedly whenever find() or select query is called.

  Thanks.
  Wonseok



    --Gordon



      -----Original Message-----
      From: Wonseok Kim [mailto:guruwons_at_gmail.com]
      Sent: Tuesday, August 29, 2006 11:21 PM
      To: persistence_at_glassfish.dev.java.net
      Subject: Re: Disable TopLink caching


      Hi, Gordon

      Could you explain NONE and Weak cache type in detail?
      Your prior exaplanation is different from my understanding of below reference.
      http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-extensions.html#TopLinkCaching

      When I made a simple test, I could get fresh result from database with NONE option, but I couldn't get fresh one with Weak option. So I'm doubtful that Weak option gurantees no caching.

      [sample test]

      //EntityManager is closed and recreated between transactions
      //create
      begin();

      Long id;
      Employee e = bean.createEmployee("Mike1", "Old");
      id = e.getId();
      commitAndClose();

      //let's update through JDBC
      Statement stmt = connection.createStatement();
      stmt.executeUpdate("UPDATE EMP SET address = 'New' WHERE EMPID = " + id);
      stmt.close();

      begin();
      Employee e2 = em.find(Employee.class, id);
      assertNotNull(e2);
      String address2 = e2.getAddress();
      println("address2 = " + address2);
      commitAndClose();

      begin();
      Employee e3 = (Employee) em.createQuery("SELECT e FROM Employee e WHERE e.id = :id")
              .setParameter("id", id).getSingleResult();
      assertNotNull(e3);
      String address3 = e3.getAddress();
      println("address3 = " + address3);
      commitAndClose();


      [result]
      1. toplink.cache.type.default="None"
      ### address2 = New
      ### address3 = New

      2. toplink.cache.type.default="Weak"
      ### address2 = Old
      ### address3 = Old

      With Weak what I got is "Old" addresses and find() does not even trigger SELECT statement.(same behaviour as default "SoftWeak" option)

      One more thing: Why NONE is not recommended? Could you explain in detail when it can be dangerous?

      -Wonseok


      On 8/30/06, Gordon Yorke < gordon.yorke_at_oracle.com> wrote:
        Marina,
            WEAK guarantees no caching. Objects may, at any time, still be loaded within the VM and reading threads may still find these objects but TopLink is not actively caching the values.
            Users who remove records between test runs will get the expected behaviour from WEAK.
        --Gordon


        -----Original Message-----
        From: Marina.Vatkina_at_Sun.COM [mailto: Marina.Vatkina_at_Sun.COM]On Behalf Of
        Marina Vatkina
        Sent: Tuesday, August 29, 2006 1:13 PM
        To: persistence_at_glassfish.dev.java.net
        Subject: Re: Disable TopLink caching


        Hello Gordon,

        Does WEAK guarantee no caching between transactions or the cache will use
        weak references and depending on GC cycles, the object might be in or out
        of the cache?

        The users are usually in a testing mode when they need this behavior, so
        they exactly know what is there in the database. And in most cases, they
        delete records from the database manually between the runs of the application.

        thanks,
        -marina

        Gordon Yorke wrote:
> Hello all,
> Cache Type default of NONE should almost never be used (there are a few cases where object have no relationships where it can be used). Instead, for those users who wish to have no TopLink caching between transactions the default Cache Type should be set to WEAK.
> As an aside, eliminating caching almost never provides users with the behaviour they envision. In a concurrent system the view a user has (managed objects) of the volatile data can not reliably be expected to be 'the database has', that's the whole reason behind developing a locking strategy.
> Also, try-catch blocks are required around each refresh call *independent* of the caching type. Unless, the user knows that the object being refreshed can never be deleted.
> --Gordon
>
> -----Original Message-----
> From: Marina.Vatkina_at_Sun.COM [mailto: Marina.Vatkina_at_Sun.COM]On Behalf Of
> Marina Vatkina
> Sent: Monday, August 28, 2006 9:54 PM
> To: persistence_at_glassfish.dev.java.net
> Subject: Re: Disable TopLink caching
>
>
> Tom,
>
> The question is (I think - Markus is on vacation this week) whether
> it's possible to disable caching between transactions, so that the
> users see the world exactly as the database does. Otherwise the user
> will need to have a try-catch block around each refresh - not an EOU
> case. :(.
>
> thanks,
> -marina
>
> Tom Ware wrote On 08/24/06 07:20,:
>
>>There is a bunch of information on extend persistence context and
>>transaction scoped persistence context in section 5.6 of the
>>specification. I believe extended persistence context is the default.
>>
>>In a transactional persistence context, the ServerSession cache
>>implements any caching used between transactions.
>>
>>In an extended persistence context, the RepeatableWriteUnitOfWork is
>>used. As a result, in an extended persistence context, you must use the
>>UnitOfWork's built-in caching which by design uses FullIdentityMap in
>>order to ensure object identity is maintained throughout its use.
>>
>>-Tom
>>
>>Markus Fuchs wrote:
>>
>>
>>
>>>Hi Tom,
>>>
>>>How can a non-extended persistence context be specified in JPA? I
>>>understand your answer that toplink.cache.type.default can be used to
>>>achieve this goal as it applies to the ServerSession cache, which
>>>implements the caching btw. transactions functionality, correct?
>>>
>>>Thanks,
>>>
>>>-- markus.
>>>
>>>Tom Ware wrote:
>>>
>>>
>>>
>>>
>>>
>>>>Hi Markus,
>>>>
>>>>In JPA, when using an extended persistence context we will cache
>>>>between transactions.
>>>>
>>>>The toplink.cache.type.default property affects the caching of the
>>>>TopLink ServerSession that underlies the EntityManagerFactory.
>>>>EntityManager's using an extended persistence context will be based on
>>>>a TopLink UnitOfWork which, in order to maintain object identity, has
>>>>a more complete cache.
>>>>
>>>>-Tom
>>>>
>>>>Markus Fuchs wrote:
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>>Hi Tom,
>>>>>
>>>>>Is it possible to disable TopLink's between transactions cache by
>>>>>setting
>>>>>
>>>>><property name="toplink.cache.type.default" value="NONE"/>
>>>>>
>>>>>in persistence.xml ?
>>>>>
>>>>>Thanks,
>>>>>
>>>>>-- markus.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>