34

I am using Hibernate and Spring for my web application.

In database operation, Hibernate is caching entities and returning them in next request without reading the actual database. I know this will reduce the load on database and improve performance.

But while this app still under construction, I need to load data from database in every request (testing reason).

Is there any way to force database read?

I became sure about the caching from this log4j message.

Returning cached instance of singleton bean 'HelloController'
DEBUG [http-bio-8080-exec-42] - Last-Modified value for [/myApp/../somePageId.html] is: -1
wrapperapps
  • 937
  • 2
  • 18
  • 30
Saif
  • 6,804
  • 8
  • 40
  • 61
  • possible duplicate of [How I can disable the second-level cache of some certain entities in Hibernate without changing annotations](http://stackoverflow.com/questions/934133/how-i-can-disable-the-second-level-cache-of-some-certain-entities-in-hibernate-w) – bartektartanus Jan 12 '15 at 15:15

5 Answers5

34

session.refresh(entity) or entityManager.refresh(entity) (if you use JPA) will give you fresh data from DB.

Predrag Maric
  • 23,938
  • 5
  • 52
  • 68
  • 1
    i am not using JPA. so do i need to change `session.get()` to `session.refresh()`? or if there is a way to check if it is coming from cache .? – Saif Jan 12 '15 at 15:31
  • 2
    No, you should use `session.refresh()` after `session.get()` because it only works with attached entities. To check if an entity is already loaded, [this thread](http://stackoverflow.com/questions/7473828/hibernate-session-contains-class-clazz-serializable-id) has some suggestions, but nothing reliable imho. – Predrag Maric Jan 12 '15 at 15:44
  • 3
    the trick with this approach is that when the entity does not exist in the database, but exists in the cache, calling `refresh()` throws `org.hibernate.UnresolvableObjectException: No row with the given identifier exists` – Adam Siemion Feb 14 '16 at 11:03
  • @adamsiemion Yes, that is something one should be aware of. – Predrag Maric Feb 14 '16 at 11:47
  • I had the same problem described in the question. With JPA it seems that `entityManager.clear()` discard in a single operation the whole cache. – danidemi Aug 05 '16 at 10:14
  • 1
    This isn't really satisfactory for retrieving multiple entities--won't refresh on every single one just create a separate query for each? I'd prefer if the initial query itself just bypassed the cache. I'm doing query.setHint("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS) ... but this doesn't seem to work either. Annoying cache! – Alkanshel Jul 23 '18 at 20:30
  • You're using Hibernate, which implements JPA, meaning you use JPA. – Dragas Nov 15 '19 at 15:11
22

Do the read within a new transaction.

For example:

...
MyDTO myDTO = fetchMyDTOById(daoId);
...
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
private MyDTO fetchMyDTOById(Long dtoId) {
    return repository.findById(dtoId);
}
wild_nothing
  • 2,845
  • 1
  • 35
  • 47
4
  • Call refresh entity session.refresh(entity)

    or

  • Open new session then call session2.get(EntityClass.class,id) it will pull the entity from the database

        Session session2=sessionFactory.openSession();                  
        EntityClass entity=(EntityClass) session2.get(EntityClass.class, id);
    
Hatem Badawi
  • 536
  • 4
  • 9
2

Please call EntityManger.clear() method, and then call repository.find() or repository.findOne() as per your requirement to select the updated data from database.

@PersistentContext EntityManager em;
@Autowired EntityReporisitory rep;
....
....
@Transactional
public void method(){
....
....
em.clear();// This line will clear the current value of entity
Entity e = rep.find(example);// In this line data will be loaded freshly from DB
....
....
}
Subhadeep Ray
  • 909
  • 6
  • 6
0

You can use a counter to ensure a cache miss. The 'counter' can be any unique value generator, such as a literal counter, or a time parameter or even a UUID. Expect a negative condition to be true.

E.g:

@Query("select p from Post p where p.id = :postId and p.postedOn <> :cacheBustingTimer")
Post fetchPostById(@Param("postId") Long postId, @Param("cacheBustingTimer") LocalDateTime cacheBustingTimer);

Sample call

Post post = postRepository.fetchPostById(postIdToFetch, LocalDateTime.now().minusYear(100));
BKaun
  • 517
  • 7
  • 17