Announcement Announcement Module
Collapse
No announcement yet.
How to turn off Hibernate Cache for query? (jpa) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to turn off Hibernate Cache for query? (jpa)

    I am using jpa with hibernate as a vendor:

    Code:
    	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    		<property name="dataSource" ref="dataSource" />
    		
    		<property name="jpaVendorAdapter">
    			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    				<property name="showSql" value="false" />
    				<property name="generateDdl" value="false" />
    				<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
    			</bean>
    		</property>
    	</bean>
    and i have a following problem:

    I've recently added a spring job (via org.springframework.scheduling.quartz.SchedulerFac toryBean) where i get some data from the database, modify it and update it.

    The problem is that when i fetch some data - the second time i do it - they are cached.
    For me this is a big problem because i can modify the data externally so i do not want a cache for certain queries.

    Right now i am making a refresh of the object but i really don't like this solution (and it will be a real pain in the ass if i add more code to the job, which i will, eventually).

    How can i enforce fetching the data without cache?
    Query returned from EntityManager (via createQuery) does not have any method like 'setCacheable(true/false)'

    The best way for me would be to add some annotation for the fetching method but i can't find how to do it with jpa.
    Last edited by fox; May 5th, 2007, 06:03 AM.

  • #2
    There's a discussion of a similar issue with Toplink here, I'm not sure how much of this translates to Hibernate.
    http://weblogs.java.net/blog/guruwon...nding_t_1.html
    Last edited by karldmoore; May 5th, 2007, 05:53 AM.

    Comment


    • #3
      thanks, Karl, for the link

      for the toplink they use:
      Code:
      query.setHint("toplink.refresh", "true")
      so i've googled this hint for hibernate

      Code:
      q.setHint("org.hibernate.cacheable", true);
      i'll play with false and let you know if this works or not. maybe someone else might have the same problem :-)

      Comment


      • #4
        That looks promising! It would be great to know how it goes.

        Comment


        • #5
          so, i've investigated the problem and i finally know how it works.


          we have three hints:

          Code:
          org.hibernate.cacheable - true/false
          
          org.hibernate.cacheMode - NORMAL / IGNORE / GET / PUT / REFRESH
          
          org.hibernate.cacheRegion - String
          first one just globally enables / disables cache (and i've read that by default it is false, so you have to explicitly set to true if you want caching)

          second one sets the cache behaviour (for me the best option would be either REFRESH, but IGNORE also should be ok)

          i've updated my queries with hints.. but the problem still remained.

          so, i've looked at the sourcecode of hibernate and i've found out the real problem


          the caching works fine (or does not work, when we turn it off :P) but the problem was in this part of the code:

          org.hibernate.loader.Loader.java:
          Code:
          for ( int i = 0; i < cols; i++ ) {
          			Object object = null;
          			EntityKey key = keys[i];
          
          			if ( keys[i] == null ) {
          				//do nothing
          			}
          			else {
          
          				//If the object is already loaded, return the loaded one
          				object = session.getEntityUsingInterceptor( key );
          				if ( object != null ) {	
          					this.log.info("object was already loaded!");
          					//its already loaded so don't need to hydrate it
          					instanceAlreadyLoaded( 
          							rs,
          							i,
          							persisters[i],
          							key,
          							object,
          							lockModes[i],
          							session 
          						);
          				}
          				else {
          					this.log.info("object was not loaded!");
          					object = instanceNotYetLoaded( 
          							rs,
          							i,
          							persisters[i],
          							descriptors[i].getRowIdAlias(),
          							key,
          							lockModes[i],
          							optionalObjectKey,
          							optionalObject,
          							hydratedObjects,
          							session 
          						);
          				}
          			}
          			rowResults[i] = object;
          		}
          If something is loaded and i want to load it again - then i will get the object that was loaded before and not the fresh one.

          I understand why this is good. When i get a list of objects from the database and those objects have reference to one specific object - that specific object will be taken from the database just once.

          On each request i have one session so the basket with loaded objects is removed at the end of the request (or maybe is cleared on request's start).

          But my taskManager is a forever living object with one binded entity manager. That "basket" is never cleared because the session stays there.

          My specific situation looks this way:

          [A]: Controller that can 'start' fleet (Entity Object) containing ships (Entity Objects) flying from OnePlanet (Entity Object) to SecondPlanet (Entity Object). I call that 'departure'
          [B]: TasksManager that looks at what exactly is going on and if the time is right - he takes fleet and moves the ships from fleet to planet. I call that 'arrival'.


          During the 'arrival' phase [B] takes the list of ships from planet (first time is ok, because he takes it from db) and updates the planet's ships with new ships that arrived with some fleet (updating planet's ships with new quantity).

          [A] can depart new fleet and modify the planet's ships quantity.

          But the next time some fleet arrives to that specific planet - [B] will try to get current list of ships on planet but the query will return objects from the basket and not from database which is my main problem. (the problem is that the [B] will not see that [A] modified the quantities of ships)


          --
          What should i do so the resolution to my problem would not be a hack, but a nicely done code?
          Last edited by fox; May 6th, 2007, 10:13 AM.

          Comment


          • #6
            Dear Fox

            I assume You mean the first level cache that is associated with a persistency context. I think if the objects becomes detached it will be reread the next time form the database. The easiest way is to close the session (EnitityManager).
            Wolfgang

            Comment


            • #7
              Hi MedlitschW,

              yes, closing entity manager will detach the objects but accessing the detached object would thow an exception and to avoid it i would have to refresh it first.

              However i have, fortunatelly, a logical point where i can reinitialize entity manager and i do not care about detached objects because in my thread loop - i do each task from scratch - there are no entities that stay alive forever


              Cheers,
              Fox

              Comment


              • #8
                How to turn off Hibernate Cache for query? (jpa)

                I am having the same problem. I have a long running batch that runs out of memory due to the executions collection filling up in the action queue. I am calling flush() and clear() on the session after every 20 saves, but clear() does not clear the executions collection. Is this a bug?

                Regards:
                Hank Freid


                >=<((((('> >=<((((('> >=<((((('>
                Last edited by Hank Freid; May 7th, 2008, 04:58 AM. Reason: for correction

                Comment

                Working...
                X