简体   繁体   中英

Hibernate: session.createQuery and session cache

What I have:

I have integrate State Pattern in my app. That means that when I change state of some entity it may cause chain reaction. Means the states of related entities also may change, and than the states of related entities to those entities and so on.

Also I use Hibernate conversatetion, which means I use MANUL flush mode.

public void handler() {
  session = beginHibernateConversation(); //open new transaction and new session (if it's needed)
  entity.changeState(session); //call chain reaction
  finishhibernateConversation(session); //manual flush, commit, and if it's needed - close session
}

What a problem:

When I use manual flush mode all changes are made to DB only on finishhibernateConversation(session) method.

I need use session.createQuery method inside changeState(session) method. But I can't see the actual entities states! Beacause all changes are stored in unflushed session and because session.createQuery doesn't matter about session context.

Question:

How to make session.createQuery consider session cache ?

A little example:

For example I have Person - Job relationship ( one-to-many ). When I change state of one job to full time I need update all other related jobs (because person could work only on one full time job).

So, I do (inside of person UPDATE request)

  1. job1.changeState('full time')
  2. [inside the first method] session.createQuery("from Job where person.id = (:id) state in (:states)") .

The problem is that the second query isn't correct, because it doesn't consider about already changed state of job1

You have a few options here, but there is no easy change for this problem.

1) Use FlushMode.AUTO . With auto flush, Hibernate flushes before doing a query to avoid this problem. There shouldn't be any conflict between auto flush and the pattern you're using, but there are other problems with auto flush. Generally in a highly concurrent environment, you can have problems with this as it will keep long database transactions.

2) When you are making a query like this, go off of the root object and query in memory. In this example, that would be something like getting the person and iterating through its Job collection.

3) Create a ThreadLocal cache that keeps track of things you might query on. This is the worst of all options, but is sometimes necessary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM