entityManager.flush() will clear the second level cache? - java

A bit confused with the entityManger.flush();
Hibernate doc for batching
https://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/chapters/batch/Batching.html
"When you make new objects persistent, employ methods flush() and clear() to the session regularly, to control the size of the first-level cache."
I am working on spring boot data jpa.
The first doubt is for Restful applications first level cache is enabled or not?
Can the entityManager.flush() clears the second level cache?
Is entityManger.flush() is similar to System.gc();

1) First level cache is created per started transaction, so its always there for each transactional method.
2) entityManager.flush(), does not clear the second level cache. It also does not clear the first level cache, it enforces any changes done in the current transaction to be pushed into the physical database.
3) Is entityManger.flush() is similar to System.gc()? No, all the objects are still on the heap and are even still managed by the current persistence context.

Related

Multiple transactions in a single hibernate session (with Spring)

Is it possible to model the following using Hibernate + Spring.
Open session
Begin transaction
Do some work
Commit
Begin transaction
More work
Commit
Close session
I use the Spring TransactionTemplate which does both session + transaction lifetime scoping.
The reason is that sometimes I have a few stages in a business process and I would like to commit after each stage completes. However I would like to continue using the same persistent objects. If I have a separate session per transaction then I get transient/detached exceptions because the original session was closed.
Is this possible?
Yes, Hibernate's Sessions can begin and commit several transactions. What you need to do is to store open session somewhere, then reuse it. Note, that Session is not a thread-safe object, but if you're sure it won't have problems with concurrency, what you need is just to use TransactionSynchronizationUtils to bind a session to the thread resources and then unbind it when desired, you can find an example here or you can take a look at OSIV and its standard implementations.
This is a very complicated thing, it's much easier and thus desirable that you close your session right away and don't reuse it, because it may bring troubles:
The objects inside of cache are not automatically evicted, thus your Session will grow in size until OutOfMemory.
The objects inside of session are not flushed unless they are dirty, thus the chance that object was changed by another user is larger and larger. Ensure that only a single user is going to change writable objects.
If some exception happens during one of steps, you have to ensure you close the session. After exception occurred inside of Session, this object is not reusable.
If transaction was rolled back, the session is cleared by Spring, thus all your objects become detached. Make sure your discard everything if at least one of transactions was rolled back.
You could achieve this using the OpenSessionInView pattern. Spring provides a javax.servlet.Filter implementation which you could use if you're working in a servlet environment (question doesn't say so). This will ensure that your Hibernate session is kept open for the duration of the request rather than just for an individual transaction.
The Javadoc on this class is pretty comprehensive and might be a good starting point.

Ehcache getting out of sync with database

On a Java EE server using CMT, I am using ehcache to implement a caching layer between the business object layer (EJBs) and the Data Access layer (POJOs using JDBC). I seem to be experiencing a race condition between two threads accessing the same record while using a self-populating Ehcache. The cache is keyed on the primary key of the record.
The scenario is:
The first thread updates the record in the database and removes the record from cache (but the database commit doesn't necessarily happen immediately - there may be other queries to follow.)
The second thread reads the record, causing the cache to be re-populated.
The first thread commits transaction.
This is all happening in a fraction of a second. It results in the cache being out of sync with the database, and subsequent reads of the record returning the stale cached data until another update is performed, or the entry expires from the cache. I can handle stale data for short periods (the typical length of a transaction), but not minutes, which is how long I would like to cache objects.
Any suggestions for avoiding this race condition?
UPDATE:
Clearing the cache after the transaction has committed would certainly be ideal. The question is, in a J2EE environment using CMT, when the caching layer is sandwiched between the business layer (stateless session EJBs) and the data access layer, how to do this?
To be clear about the constraints this imposes, the method call in question may or may not be in the same transaction as additional method calls that happen before or after. I can't force a commit (or do this work in a separate transaction) since that would change the transaction boundaries from what the client code expects. Any subsequent exceptions would not roll back the entire transaction (unneseccarily clearing the cache in this case is an acceptable side-effect). I can't control the entry points into the transaction, as it is essentially an API that clients can use. It is not reasonable to push the resonsiblity of clearing the cache to the client application.
I would like to be able to defer any cache clearing operations until the entire transaction is committed by the EJB container, but I have found no way to hook into that logic and run my own code with a stateless session bean.
UPDATE #2:
The most promising solution so far, short of a major design change, is to use ehcache 2.0's JTA support: http://ehcache.org/documentation/apis/jta
This means upgrading to ehcache 2.x and enabling XA transactions for the database as well, which could potentially have negative side-effects. But it seems like the "right" way.
You are using transactions - it makes more sense to remove the cache after the commit, that is when the change really happens.
That way you see the old data only during the length of the transaction, and all reads afterwards have the latest view.
Update: Since this is CMT specific, you should look at the SessionSynchronization interface, and it's afterCompletion() method. This is showed in this tutorial.

Where does the responsibility lie to ensure the ACID properties of a transaction?

I was going through ACID properties regarding Transaction and encountered the statement below across the different sites
ACID is the acronym for the four properties guaranteed by transactions: atomicity, consistency, isolation, and durability.
**My question is specifically about the phrase.
guaranteed by transactions
**. As per my experience these properties are not taken care by
transaction automatically. But as a java developer we need to ensure that these properties criteria are met.
Let's go through for each property:-
Atomicity:- Assume when we create the customer the account should be created too as it is compulsory. So now during transaction
the customer gets created while during account creation some exception oocurs. So the developer can now go two ways: either he rolls back the
complete transaction (atomicity is met in this case) or he commits the transaction so customer will be created but not the
account (which violates the atomicity). So responsibility lies with developer?
Consistency:- Same reason holds valid for consistency too
Isolation :- as per definition isolation makes a transaction execute without interference from another process or transactions.
But this is achieved when we set the isolation level as Serializable. Otherwis in another case like read commited or read uncommited
changes are visible to other transactions. So responsibility lies with the developer to make it really isolated with Serializable?
Durability:- If we commit the transaction, then even if the application crashes, it should be committed on restart of application. Not sure if it needs to be taken care by developer or by database vendor/transaction?
So as per my understanding these ACID properties are not guaranteed automatically; rather we as a developer sjould achieve them. Please let me know
if above understanding regarding each point is correct? Would appreciate if you folks can reply for each point(yes/no will also do.
As per my understanding read committed should be most logical isolation level in most application, though it depends on requirement too.
The transactions guarantees ACID more or less:
1) Atomicity. Transaction guarantees all changes are made or none of them. But you need to manually set the start and end of a transaction and manually perform commit or rollback. Depending on the technology you use (EJB...), transactions are container-managed, setting the start and end to the whole "method" you are creating. You can control by configuration if a method invoked requires a new transaction or an existing one, no transaction...
2) Consistency. Guaranteed by atomicity.
3) Isolation. You must define the isolation level your application needs. Default value is defined depending upon the database, container... The commonest one is READ COMMITTED. Be careful with locks as can cause dead-lock depending on your logic and isolation level.
4) Durability. Managed entirely by the database. If your commit executes without error, nearly all database guarantees durability of changes, but some scenarios can cause to not guarantee that (writes to disk are cached in memory and flushed later...)
In general, you should be aware of transactions and configure it in the container of declare by code the star and end (commit, rollback).
Database transactions are atomic: They either happen in their entirety or not at all. By itself, this says nothing about the atomicity of business transactions. There are various strategies to map business transactions to database transactions. In the simplest case, a business transaction is implemented by one database transaction (where a business transaction is aborted by rolling back the database one). Then, atomicity of database transactions implies atomicity of business transactions. However, things get tricky once business transactions span several database transactions ...
See above.
Your statement is correct. Often, the weaker guarantees are sufficient to prove correctness.
Database transactions are durable (unless there is a hardware failure): if the transaction has committed, its effect will persist until other transactions change the data. However, calling code might not learn whether a transaction has comitted if the database or the network between database and calling code fails. Therefore
If we commit the transaction, then even if application crash, it should be committed on restart of application.
is wrong. If the transaction has committed, there is nothing left to do.
To summarize, the database does give strong guarantees - about the behaviour of the database. Obviously, it can not give guarantees about the behaviour of the entire application.

Why does hibernate/ehcache second level cache always miss within the same session?

I have a long-running EntityManager which I periodically clear(). I have a read-write cache configured on one of my entities.
I have done some investigation and I can see that the entity is present in the cache. I can even see a cache hit from net.sf.ehcache.Cache.searchInStoreWithStats(). However, ehcache will not return the entity if its timestamp is later than the timestamp when the session was created: see AbstractReadWriteEhcacheAccessStrategy.get(Object, long).
What is the reason for this behaviour? Is there a way I can customise hibernate or ehcache to achieve cache hits within a single EntityManager?
It looks like this is a property of a read-write cache: you can't fetch an entity from the cache that was created in the same session.
A non-strict read-write cache doesn't compare timestamps, so this does achieve a cache hit after the first load().
Even better, a transactional cache populates the cache after persist(), so the very first load() will result in a cache hit. Since my interaction with the databse is entirely within a single thread in a single JVM, I believe this is safe to use.
As the JavaDoc say: The timestamp says the Entity was created after the transaction started, so the transaction can't possibly see it (as per ACID).
So it seems that you have several transactions, say A and B. You start B, then A, then A creates instance X and then B tries to look up X -> cache miss since A isn't committed, yet (for example).

Hibernate/Ehcache: evicting collections from 2nd level cache not synchronized with other DB reads

I have an application using JPA, Hibernate and ehcache, as well as Spring's declarative
transactions. The load on DB is rather high so everything is cached to speed things up,
including collections. Now it is not a secret that collections are cached separately
from the entities that own them so if I delete an entity that is an element of such
cached collection, persist an entity that should be an element of one, or update an
entity such that it travels from one collection to another, I gotta perform the eviction
by hand.
So I use a hibernate event listener which keeps track of entities being inserted, deleted
or updated and saves that info for a transaction synchronization registered with Spring's
transaction manager to act upon. The synchronization then performs the eviction once the
transaction is committed.
Now the problem is that quite often, some other concurrent transaction manages to find
a collection in the cache that has just been evicted (these events are usually tenths of a
second apart according to log) and, naturally, causes an EntityNotFoundException to occur.
How do I synchronize this stuff correctly?
I tried doing the eviction in each of the 4 methods of TransactionSynchronization (which
are invoked at different points in time relative to transaction completion), it didn't help.
Essentially what you need to do is to force a read from the database in the event that a collection is in the process of or has just been evicted. One way to do this would be to mark the collection as dirty as soon as a request to evict it has been received but before entering the transaction to change it. Any concurrent transaction which comes along will check the dirty flag and if its set to true, it should get the data from the database otherwise it can read from the cache. You might need to change your DB transaction settings so that concurrent transactions block till the one updating the data finishes so that correct data is read from the DB. Once the transaction finishes, you can then reset the dirty flag to false.
You can also create a lock on the cached collection when an update, insert or delete is due for as long as the eviction lasts. This will ensure that no other transaction can read/change the cached collection till the eviction process finishes.
Why can't you must keep the collections up to date? i.e. when you add an object, add the object to the collection it belongs to. When you delete an object, remove it from the collection it is in. In my experience when using a cache with hibernate or jpa the state of the object (not the state of the database) is cached so you need to make sure your object model in memory is in sync with the object model on the database.
Or am I missing something? Why can't you simply keep the collections uptodate?
i think you must refer this link : -
Hibernate: Clean collection's 2nd level cache while cascade delete items
see, hibernate does not actually delete the object from the cache.. rest u can get the answer from above link

Categories