Reputation: 101
Java web
Spring MVC framework
In my service level, I wrote a @Transactional
method. In that method, I update some data in database and then read the data from the database later.
What surprises me is that when several requests come, inside the same thread, the data change is visible(which is supposed to be), but the data change is not visible in other thread.
Isn't different threads of one method build as one transaction?
And what should I do if I still want to use transaction and I want the same method called in different threads be in one transaction (the change of the data can be seen by each other)?
Upvotes: 3
Views: 10083
Reputation: 6285
From Professional Java for Web Applications by Nicholas S. Williams
Using Threads for Transactions and Entity Managers
The transaction scope is limited to the thread the transaction begins in. The transaction manager then links the transaction to managed resources used in the same thread during the life of the transaction. When using the Java Persistence API, the resource you work with is the
EntityManager
. It is the functional equivalent of Hibernate ORM’sSession
and JDBC’sConnection
. Normally, you would obtain anEntityManager
from theEntityManagerFactory
before beginning a transaction and performing JPA actions. However, this does not work with the Spring Framework model of managing transactions on your behalf. The solution to this problem is theorg.springframework.orm.jpa.support.SharedEntityManagerBean
. When you configure JPA in Spring Framework, it creates aSharedEntityManagerBean
that proxies theEntityManager
interface. This proxy is then injected into your JPA repositories. When anEntityManager
method is invoked on this proxy instance, the following happens in the background:
➤➤ If the current thread already has a real
EntityManager
with an active transaction, it delegates the call to the method on thatEntityManager
.
➤➤ Otherwise, Spring Framework obtains a new
EntityManager
from theEntityManagerFactory
, starts a transaction, and binds both to the current thread. It then delegates the call to the method on thatEntityManager
. When the transaction is either committed or rolled back, Spring unbinds the transaction and theEntityManager
from the thread and then closes theEntityManager
. Future@Transactional
actions on the same thread (even within the same request) start the process over again, obtaining a newEntityManager
from the factory and beginning a new transaction. This way, no two threads use anEntityManager
at the same time, and a given thread has only one transaction and oneEntityManager
active at any given time.
(I paraphrased it a little the above piece)
I think its self explanatory and answers your question. But I would like to add that, if you were not to use Spring MVC then you would have gotten the session using SessionFactory
in Hibernate. Hibernate Session
s represent the life of a transaction from start to finish. Depending on how your application is architected, that might be less than a second or several minutes; and in a web application, it could be one of several transactions in a request, a transaction lasting an entire request, or a transaction spanning multiple requests. A Session
, which is not thread-safe and must be used only in one thread at a time, is responsible for managing the state of entities.
Upvotes: 10
Reputation: 5004
you may want to play with isolation
parameter of@Transactional
annotation. Spring by default uses.. hm.. DEFAULT
which is set by database, so may be different. You can try to use: READ_UNCOMMITTED
. More info: http://www.byteslounge.com/tutorials/spring-transaction-isolation-tutorial
Upvotes: 5