Spring #Transactional(isolation=Isolation.READ_UNCOMMITTED) vs Spring Data #Lock(LockModeType.None) - spring

Some systme info, it's using Spring, Spring Data, JPA and Hibernate.
My question is, what's the difference between the 2? See below:
//this uses plain JPA, and uses Spring's Transactional
#Transactional(isolation=Isolation.READ_UNCOMMITTED)
public List getData() {
//code
}
//this uses Spring Data
#Lock(LockModeType.None)
public List getData() {
//code
}

Locking and Transaction are two different things, but anyway...
This isolation level allows dirty reads. One transaction may see uncommitted changes made by some other transaction.
/**
* A constant indicating that dirty reads, non-repeatable reads and phantom reads
* can occur. This level allows a row changed by one transaction to be read by
* another transaction before any changes in that row have been committed
* (a "dirty read"). If any of the changes are rolled back, the second
* transaction will have retrieved an invalid row.
* #see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
*/
READ_UNCOMMITTED
LockModeType
Lock modes can be specified by means of passing a LockModeType
argument to one of the EntityManager methods that take locks (lock,
find, or refresh) or to the Query.setLockMode() or
TypedQuery.setLockMode() method.
Lock modes can be used to specify either optimistic or pessimistic
locks.
So, as it said LockModeType.NONE is default for annotations (JPA, annotations left and right) I guess when you use EntityManager.find(Class, Object) the default LockModeType is used.
I suggest to you this link to see some examples to Pessimistic and Optimistic lock, and this link to see Transactional examples

Related

Spring JPA: keeping the persistence context small

How can I keep the persistence context small in a Spring JPA environment?
Why: I know that by keeping the persistence context small, there will be a significant performance boost!
The main problem area is:
#Transactional
void MethodA() {
WHILE retrieving next object of 51M (via a stateless session connection) DO
get some further (readonly) data
IF condition holds THEN
assessment = retrieve assession object (= record from database)
change assessment data
save the assessment to the database
}
Via experiments in this problem domain I know that when cleaning the persistence context every 250 iterations, then the performance will be a lot better.
When I add these lines to the code, so every 250 iterations:
#PersistenceContext
private EntityManager em;
WHILE ...
...
IF counter++ % 250 == 0 THEN
em.flush()
em.clear()
}
Then I get errors like "cannot reliably perform the flush operation".
I tried to make the main Transactional read-only and the asssessment-save part 'Transaction-requires-new', then I get errors like 'operating on a detached entity'. Very strange, because I never revisit an open entity.
So, how can I keep the persistence context small?
Have tried 10s of ways. Help is really appreciated.
I would suggest you move all the condition logic into your query so that you don't even have to load that many rows/objects. Or even better, write an update query that does all of that in a single transaction so you don't need to transfer any data at all between your application and database.
I don't think that flushing is necessary with a stateless session as it doesn't keep state i.e. it flushes and clears the persistence context after every operation, but apart from that, I also think this this might not be what you really want as that could lead to re-fetching of data.
If you don't want the persistence context to fill up, then use DTOs for fetching the data and execute update statements to flush the changes.

Spring jpa: Do I need to add #Transactional annotation on retrieval queries

I am using EntityManger for the retrieval queries in my spring boot application. An example snippet is given below.
#Repository
public class EntityManagerUtil {
#PersistenceContext
private EntityManager entityManager;
public List<Employee> getAll(){
// Use entityManager here
}
}
I need some clarity on the below questions.
a. Is EntityManger will be created for every call (or) will it be a singleton? (I tried printing entityManager, it is returning the same object for all the calls)
b. Is this approach leads to any connection leaks?
c. Do I need to put #Transactional annotation on reading operations?
I am using spring boot version 2.0.3-release
a) See M Deinum's comments about the injected EntityManager being a proxy. The normal situation for JPA is to have an EntityManager tied to each thread, Spring sets this up for you and provides a proxy to delegate to the actual EntityManager. So this arrangement is safe.
b) Connection leaks happen when you don't return a database connection to the pool. Spring takes care of providing a connection and cleaning up resources so in the normal course of things you shouldn't get connection leaks. If you ignore the facilities Spring gives you like JdbcTemplate and insist on writing your own JDBC code, then you can cause resources to leak. If your code tries to use an EntityManager intended for another thread you will get an exception, it will not fail silently, and it will not (in itself) cause a connection leak.
c) You are using an RDBMS so you will have a transaction.
Apparently some people think transactions are optional, but they really aren't. If you don't specify them then Spring will wrap each operation in its own transaction. Not only are you just better off in general being explicit about this, but you can mark the transaction as readonly, which lets Spring perform some optimizations, see Oliver Drotbohm's answer for details. So maybe you can get by without it for some cases (such as, each http request results in only one database operation), but it is in your interest to use it.

Spring Transaction Management- Multiple request to same URL

I am trying to create an API in Spring Boot using #Transactional annotation regarding bank fund transfer.
Now I want to know - if there are multiple calls to the same API at the same time, how to manage transaction between them. Suppose for example transferBalance method is called by Transaction X which transfers funds from accounts A to B and another transaction Transaction Y transfer funds from B to C. Both transactions occur at the same time. How would these transactions be handled? What propagation should it have and also what about the isolation?
Check this below changes: for your case check bold description below.
if more than one transaction can also go with SERIALIZED
Isolation level defines how the changes made to some data repository by one transaction affect other simultaneous concurrent transactions, and also how and when that changed data becomes available to other transactions. When we define a transaction using the Spring framework we are also able to configure in which isolation level that same transaction will be executed.
#Transactional(isolation=Isolation.READ_COMMITTED)
public void someTransactionalMethod(Object obj) {
}
READ_UNCOMMITTED isolation level states that a transaction may read data that is still uncommitted by other transactions.
READ_COMMITTED isolation level states that a transaction can't read data that is not yet committed by other transactions.
REPEATABLE_READ isolation level states that if a transaction reads one record from the database multiple times the result of all those reading operations must always be the same.
SERIALIZABLE isolation level is the most restrictive of all isolation levels. Transactions are executed with locking at all levels (read, range and write locking) so they appear as if they were executed in a serialized way.
Your doubt has nothing to do with #Transactional.
Its simple question of concurrency.
Actually both the transaction, form a to b and form b to c can work concurrently.
By putting #Transactional states something like
works out whether a given exception should cause transaction rollback by applying a number of rollback rules, both positive and negative. If no rules are relevant to the exception, it behaves like DefaultTransactionAttribute (rolling back on runtime exceptions).

Why does Hibernate not support nested transactions outside of Spring?

I am using Hibernate4 but not Spring. In the application I am developing I want to log a record of every Add, Update, Delete to a separate log table. As it stands at the moment my code does two transactions in sequence, and it works, but I really want to wrap them up into one transaction.
I know Hibernate does not support nested transactions, only in conjunction with Spring framework. I´ve read about savepoints, but they´re not quite the same thing.
Nothing in the standards regarding JPA and JTA specification has support for nested transactions.
What you most likely mean with support by spring is #Transactional annotations on multiple methods in a call hierarchie. What spring does in that situation is to check is there an ongoing transaction if not start a new one.
You might think that the following situation is a nested transaction.
#Transactional
public void method1(){
method2(); // method in another class
}
#Transactional(propagation=REQUIRES_NEW)
public void method2(){
// do something
}
What happens in realitiy is simplified the following. The type of transactionManager1 and transactionManager2 is javax.transaction.TransactionManager
// call of method1 intercepted by spring
transactionManager1.begin();
// invocation of method1
// call of method 2 intercepted by spring (requires new detected)
transactionManager1.suspend();
transactionManager2.begin();
// invocation of method2
// method2 finished
transactionManager2.commit();
transactionManager1.resume();
// method1 finished
transactionManager1.commit();
In words the one transaction is basically on pause. It is important to understand this. Since the transaction of transactionManager2 might not see changes of transactionManager1 depending on the transaction isolation level.
Maybe a little background why I know this. I've written a prototype of distributed transaction management system, allowing to transparently executed methods in a cloud environment (one method gets executed on instance, the next method might be executed somewhere else).

Spring Bean Hangs on Method with #Transactional

Just a little background , I'm a new developer who has recently taken over a major project after the senior developer left the company before I could develop a full understanding of how he structured this. I'll try to explain my issue the best I can.
This application creates several MessageListner threads to read objects from JMS queues. Once the object is received the data is manipulated based on some business logic and then mapped to a persistence object to be saved to an oracle database using a hibernate EntityManager.
Up until a few weeks ago there hasn't been any major issues with this configuration in the last year or so since I joined the project. But for one of the queues (the issue is isolated to this particular queue), the spring managed bean that processes the received object hangs at the method below. My debugging has led me to conclude that it has completed everything within the method but hangs upon completion. After weeks of trying to resolve this I'm at end of my rope with this issue. Any help with this would be greatly appreciated.
Since each MessageListner gets its own processor, this hanging method only affects the incoming data on one queue.
#Transactional(propagation = Propagation.REQUIRES_NEW , timeout = 180)
public void update(UserRelatedData userData, User user,Company company,...)
{
...
....
//business logic performed on user object
....
......
entityMgr.persist(user);
//business logic performed on userData object
...
....
entityMgr.persist(userData);
...
....
entityMgr.flush();
}
I inserted debug statements just to walk through the method and it completes everything including entityMgr.flush.().
REQUIRES_NEW may hang in test context because the transaction manager used in unit testing doesn't support nested transactions...
From the Javadoc of JpaTransactionManager:
* <p>This transaction manager supports nested transactions via JDBC 3.0 Savepoints.
* The {#link #setNestedTransactionAllowed "nestedTransactionAllowed"} flag defaults
* to {#code false} though, since nested transactions will just apply to the JDBC
* Connection, not to the JPA EntityManager and its cached entity objects and related
* context. You can manually set the flag to {#code true} if you want to use nested
* transactions for JDBC access code which participates in JPA transactions (provided
* that your JDBC driver supports Savepoints). <i>Note that JPA itself does not support
* nested transactions! Hence, do not expect JPA access code to semantically
* participate in a nested transaction.</i>
So clearly if you don't call (#Java config) or set the equivalent flag in your XML config:
txManager.setNestedTransactionAllowed(true);
or if your driver doesn't support Savepoints, it's "normal" to get problem with REQUIRES_NEW...
(Some may prefer an exception "nested transactions not supported")
This kind of problems can show up when underlying database has locks from uncommitted changes.
What I would suspect is some other code made inserts/deletes on userData table(s) outside transaction or in a transaction which takes very long time to execute since it's a batch job or similar. You should analyze all the code referring to these tables and look for missing #Transactional.
Beside this answer, you may also check for the isolation level of your transaction — perhaps it's too restrictive.
Does the update() method hang forever, or does it throw an exception when the timeout elapses?
Unfortunately I have the same problem with Propagation.REQUIRES_NEW. Removing it resolves the problem. The debugger shows me that the commit method is hanging (invoked from #Transactional aspect implementation).
The problem appears only in the test spring context, when the application is deployed to the application server it works fine.

Resources