Hibernate has a Stateless Version of its Session: Does something similar exist for the JPA EntityManager? I.e. an EntityManager that does not use the first level cache?
From JPA point of view:
javax.persistence.EntityManager stands for 1st level cache (persistence context, transactional cache)
javax.persistence.EntityManagerFactory stands for 2nd level cache (shared cache)
A given persistence provider may implement additional caching layers. Additionally JDBC Driver API may be treated as low-level cache for storing columns/tables and caching connections/statements. It's however transparent to JPA.
Both javax.persistence.EntityManager and org.hibernate.StatelessSession offer similar APIs.
You cannot disable 1st level cache with EntityManager beacuse these two things are equivalent. You can however:
skip 1st level cache by using createQuery, createNamedQuery, createNativeQuery for querying and bulk updates/deletes (the persistence context is not updated to reflect their results). Such queries should be executed in their own transaction thus invalidating any cached entities, if any. Transaction-scoped entity manager (means stateless) should be used as well.
disable 2nd level cache by setting up <shared-cache-mode>NONE</shared-cache-mode> in persistence.xml or javax.persistence.sharedCache.mode in properties
Not part of the JPA API or spec. Individual implementations may allow disabling the L1 cache. DataNucleus JPA, the one I have used, does allow this
On an interface point of view, RDBMS usually respect the ACID constraints, a stateless option would be very specific. I guess this is the reason why Hibernate proposes this feature but not the specification.
To disable the cache, you have implementation-specific configurations (here is the doc for EclipseLink). The #Cacheable annotation (JPA 2.0) at the entity level is standard.
But if you would like to perform bulk operations, this would not do the job. Anyway, such a behavior would be implementation-specific.
Related
In he famous book "Java persistence with Hibernate" we can read the following:
"A persistence context is a cache of persistent entity instances.... Automatic dirty checking is one of the benefits of this caching. Another benefit is repeatable read for entities and the performance advantage of a unit of work-scoped cache... You don’t have to do anything special to enable the persistence context cache. It’s always on and, for the reasons shown, can’t be turned off.
Does this mean that one can never achieve a transaction isolation level "Read uncommitted" with Hibernate?
Does this mean that one can never achieve a transaction isolation level "Read uncommitted" with Hibernate?
No, it doesn't. Hibernate offers application-level repeatable reads for entities. That's different than DB-level repeatable reads which applies to any query.
So, if you want a custom isolation level, like REPEATABLE_READ for all the queries executed by a given transaction, not just for fetching entities, then you can set it like this:
#Transactional(isolation = Isolation.REPEATABLE_READ)
public void orderProduct(Long productId) {
...
}
Now, your question title says:
(How) can we achieve isolation level Read Uncommitted with Hibernate / JPA?
If you are using Oracle and PostgreSQL, you cannot do that since Read Uncommitted is not supported, and you'll get READ_COMMITTED instead.
For SQL Server and MySQL, set it like this:
#Transactional(isolation = Isolation.READ_UNCOMMITTED)
Indeed, hibernate does offer repeateble reads thorugh its first-level cache (Persistence Context) as cited in the book
"Transactions and concurrency control" by Vlad Mihalcea.
as follows:
Some ORM frameworks (e.g. JPA/Hibernate) offer application-level repeatable reads. The first snapshot of any retrieved entity is cached in the currently running Persistence Context. Any successive query returning the same database row is going to use the very same object that was previously cached. This way, the fuzzy reads may be prevented even in Read Committed isolation level.
However, according to the same book above, it seems that using Spring with JPA / hibernate allows customizing the transaction isolation level.
In the book above we can also read the following:
Spring supports transaction-level isolation levels when using the JpaTransactionManager. For JTA transactions, the JtaTransactionManager follows the Java EE standard and disallows overriding the default isolation level. As a workaround, the Spring framework provides extension points, so the application developer can customize the default behavior and implement a
mechanism to set isolation levels on a transaction basis.
Is there any way in Spring Data to disable tracking changes (like EntityFramework) when loading an entity with lots of records(Say 100000 records)? I know we can write a view on DB and point an entity to it so. But it looks like over complication as in EntityFramework you can use AsNoTracking().
Take a look at Hibernate's StatelessSession. From the Documentation:
A stateless session does not implement a first-level cache nor
interact with any second-level cache, nor does it implement
transactional write-behind or automatic dirty checking, nor do
operations cascade to associated instances. Collections are ignored by
a stateless session. Operations performed via a stateless session
bypass Hibernate's event model and interceptors. Stateless sessions
are vulnerable to data aliasing effects, due to the lack of a
first-level cache.
We need to cache the results of a query; the query returns the whole table of a database. The problem is that the database is changed externally by other application; the Java application making the query is notified with the exact primary key of the row changed.
Is it possible to replace only the changed element from the query cache, not the whole list?
Is this the 1st level cache (from EntityManager) 2nd level Cache (from EntityManagerFactory) or a different cache?
If it is possible can this be done from JPA?
entityManager.refersh(entity);
or is this query cache the 2nd level JPA cache:
entityManagerFactory.getCache().evict(cls, primaryKey);
or only possible through Hibernate/EclipseLink API?
If is not possible, in order to achieve this, would calling entityManager.find() on all elements do it?
I haven't find anything useful neither in Hibernate documentation nor in EclipseLink documentation. Hibernate supports regions and refreshing only regions, but we need entity-level refresh granularity.
Later edit to clarify my findings.
Following the link posted by #Chris in the comment I have found out that what I wanted is actually supported by EclipseLink but only for Oracle Database (there is possible to implement own handler for other vendors; but the call from database is not standardized and differs from vendor to vendor). I have not found if Hibernate supports this or not.
Anyhow the query cache from EclipseLink had some very poor performance compared with Spring Cache (based on CocurrentMap) or with custom based cache so will remain with Spring Cache or Custom Cache over Spring Jdbc.
EntityManager.refresh() is what you want - it refreshes the entity from what is in the database. This should also update the entity in the shared cache if you are not in a transaction, otherwise you may need to use the entityManagerFactory.getCache().evict(cls, primaryKey); as well to clear the second level shared cache so it can be read into it as well later on.
When calling EntityManager.flush(), will it flush the second level cache too? I tried Googling and I also tried flushing it and it seems like it does, but it would be good to have it confirmed.
Edit: Now it does not seem like it flush the second level cache.
JPA has no notion of a second-level cache (it isn't part of the spec). So the behavior of the second-level cache depends entirely upon the JPA provider. What are you using Hibernate, EclipseLink, OpenJPA?
Update: I stand partially corrected, JPA 2.0 introduces a few options to control second-level cache usage (like #Cachable)
The L2 cache ought (by default, in any sensible JPA implementation) to be updated at commit not flush, but this is not mandated in the JPA2 spec, so you're down to implementation specifics. DataNucleus certainly only updates it at commit. If an L2 cache was updated at flush, and then those objects changes rolled back, this leads to potential invalid/non-persistent data being read. Some may allow that as an option.
Title says it all: What is the difference between a UserTransaction and an EntityTransaction?
My rudimentary understanding is that UserTransaction is used when JTA is required (e.g. to do queries on mulitple things), and that EntityTransaction is used when JPA only is required (e.g. when the query is atomic).
Is that the only difference between the two or is there more to it than that?
My rudimentary understanding is that
UserTransaction is used when JTA is
required (e.g. to do queries on
mulitple things), and that
EntityTransaction is used when JPA
only is required (e.g. when the query
is atomic).
That's basically right, but your description of "multiple things" and "atomic" is a bit strange. JTA allows the developper to use distributed transaction to perform changes on multiples resources (database, JMS broker, etc.) atomically (all-or-nothing). If only one resource is accessed (e.g. one single database), you don't need JTA, but the transaction is still atomic (all-or-nothing). That's for instance the case when you use a regular JDBC transaction on one database.
Considering UserTransaction vs. EntityTransaction:
If JPA is use stand-alone, you use EntityTransaction to demarcate the transaction yourself.
If JPA is used within a managed environment where it integrates with JTA, you use UserTransaction. The EntityManager hooks itself into the JTA distributed transaction manager. The only subtlety I'm aware of considers the flush of the changes. When EntityTransaction is used, JPA know it needs to flush the changes. If transaction are controlled using UserTransaction, it needs to register a callback using JTA registerSynchronization, so that the changes are flushed to the database before the transaction completes. If you use EJB with CMT (container managed transaction), you don't even need to use UserTransaction: the app server starts and stops the transactions for you.
Related questions:
What is difference between UserTransaction and EntityManager.getTransaction() (duplicate)
XA and non-XA datasource with Spring/Hibernate (related)