Should I ever use #Transactional on a Service class - java

I have a web application that uses Spring NamedJDBCTemplate, and all the calls to database are select statements.
In this case should i use #Transactional in my service class that calls the DAO class that inturn fires select statements to DB.
According to Transaction statergies listing 10 suggests to not use #Transactional for reads. Will i be bringing an overhead by using #Transactional and also i dont want to miss the AOP advises that i can bring in for #Transactional in future.

Yes, you should always access the database from inside a transaction. Not doing it will in fact create a transaction for every select statements.
Transactions aren't just useful for atomicity of updates. They also provide isolation guarantees. For example, (depending on the isolation level) reading the same row twice in a single transaction can return you the same data, and thus make sure you don't have incoherences in the read data. Doing it with multiple transactions won't provide any such guarantee.

I think the best way is to use #Transactional and set it as Supported not Required for such service
in this way if your service call outside a transaction it will not start a Transaction and if it calls from other service that is Transactional and already start a transaction it will participate in that transaction.
for example think that one service required to call two services in first one some data will inserted or updated and other one is just a select that return those data if these two service don't participate in single transaction the second service will not return data because the transaction start in calling service not committed yet .

Related

Example of Propagation in spring data JPA

I am trying to understand the propagation attribute of #Transactional annotation in Spring Data JPA. I have read enough theory. But I do not understand(nor can I find anywhere on internet) the real-life scenario where I need to use the PROPAGATION_REQUIRED in place of PROPAGATION_REQUIRES_NEW. I understand the theory that PROPAGATION_REQUIRED can utilize the existing transaction and PROPAGATION_REQUIRES_NEW will start a new transaction each time. But I could not understand two things -
How does it matter to me as a programmer? or in which used cases one is preferred over other?
Is the "TRANSACTION" we are talking about is a spring transaction or a database transaction
In Spring, if a method that is annotated with #Transactional calls another method annotated with #Transactional, the transaction is started at the beginning of the first method and commited after the second method is finished.
Requiring a new transaction can be helpful, if you have a sequence of methods that are transactional but you want to commit a transaction half way through the sequence.
Or maybe you have a method that should always open it's own transaction and you want to make sure it does so, even if it is called by another transactional method.

How does Hibernate control the transaction with multiple session.update()s if you don't commit the transaction explicitly?

I have inherited a system that uses Spring MVC and Hibernate that stores into a DB2 database. Recently it started having what looks like a deadlock problem reported by DB2 so I've been working on debugging it. I'm not a Spring or Hibernate expert but I know some of both.
The code is structured like this:
controller -> service -> one or more DAO classes that performs the updates
In the situation where the problem occurs the controller calls a service method annotated with #Transactional and #Override. The service goes to a DAO class annotated with #Repository and calls multiple methods annotated with #Transactional and #Override. That is the structure of code.
One controller calls one service method. The service method calls multiple DAO methods. Most of the DAO methods are marked #Transactional and #Override. A few have REQUIRES_NEW in the #Transactional. Also in each DAO method the Session is gotten by SessionFactory.getCurrentSession().
First question: with this approach where does the transaction start and where is the ultimate commit? And the rollback? None of this is explicitly coded.
The deadlock comes when one of the methods updates a record and then a subsequent method deletes that same record. If you are wondering why anyone wants to do this the update adds the user id of the person wanting to delete the information in the record so that it can be saved by a stored process to another table. Then the second method call deletes the record.
The original coder tried adding REQUIRES_NEW to the #Transactional thinking a new transaction would ensure the update would happen. But the deadlock still happens at irregular intervals.
I tried changing the update to a native SQL call but Hibernate won't let me start another transaction since one is already open.
Anyone have any guidance here?
The transaction starts when a method (which class or the method itself firstly annotated with #Transactional in the call chain) called from outside (it must call from outside of the class, because the annotation "creates" a proxy). Any other annotated class/methods in the chain with default propagation level will join to that transaction. When call a method with transactional marked as REQUIRES_NEW, the parent transaction will be suspended (if exists) and the new transaction starts. Note that if you call annotated method from other method in the same class, then it wont go throught the proxy, so it same as you delete the annotation. The commit happened right after the method who start the transaction return. Same as rollback, it will after exception is thrown. Deadlock can come from different places, it is hard to find out, even if you have code. It can for example come from update and stored procedure try to lock some rows and cyclic waiting happend etc...
I have a naive image, what happen in the background.
There are two class ui and service. The service is annotated as #Transactional.
Spring create the proxy, and all calls come from outside go through it. Before the real method will be called, it start the transaction, after that it will commit.

Is it good to make TransactionAttributeType.NOT_SUPPORTED if method doesn't persist any entity

If I have nested bean methods which just fetching data from the database. (i.e GET API). So will it be beneficial to mark all bean methods as TransactionAttributeType.NOT_SUPPORTED? Will it help in increase in performance as JTA is not managing any transaction for this?
This is exactly the purpose of using NOT_SUPPORTED, to increase performance. Infact as stated by Oracle:
NotSupported Attribute
If the client is running within a transaction and invokes the
enterprise bean’s method, the container suspends the client’s
transaction before invoking the method. After the method has
completed, the container resumes the client’s transaction.
If the client is not associated with a transaction, the container does
not start a new transaction before running the method.
Use the NotSupported attribute for methods that don’t need
transactions. Because transactions involve overhead, this attribute
may improve performance.
So, it is a perfect fit for all the select or find business methods, which purpose is maybe to fill a data table on screen.
NOT_SUPPORTED is useful if there is a processing that would cause an exception if invoked with transaction context. For example invoking stored procedure containing DDL code withing context of XA processing will cause an exception to occur. If changing stored procedure is not an option use NOT_SUPPORTED attribute as work around and suspend the transaction prior to invocation of method containing problematic stored procedure.
If transaction roll back is allowed in read only transaction use SUPPORTS , if transaction roll back is not allowed in read only transaction use NOT_SUPPORTED.
This article says:"No, it doesn't make sense to use the NOT_SUPPORTED transaction propagation for read-only queries". It's written Vlad Mihalcea who is a JPA expert.
Does TransactionAttributeType.NOT_SUPPORTED make sense for retrieving entities?

where to define transaction boundries in java (#Service or #DAO level), Any Suggestions

where to define transaction boundries in java (#Service or #DAO level), Any Suggestions
We need to manage transaction between multiple services.
Depending on your persistence technology some kind of transactions might be needed to persist anything at all. Thus you may want a transaction on a DAO-level for e.g. testing the DAO layer. If e.g. controllers have direct access to DAOs you'll need transactions on DAOs, too.
What you may want to do is declaring a transaction on the service-level and the DAO-level reusing a provided transaction.
Read the great spring reference on transactions as well as the spring data reference for ideas.
Usually I recommend to use Transaction in Service, but it depends on....
In case of Service,you will get ability to create batch of actions in the one transaction.
For example start transaction. read, modify more than one entities, update, delete whatever. close transaction.

Is explicit transaction creation required for database reads when using JpaTemplate?

In our application we mainly use Spring #Transactional annotations together with JpaTemplate and Hibernate for database interaction. One part of the project, however, communicates with a different database, and hence we cannot use #Transactional here as a different transactionManager is required.
Here, for database updates, we explicitly create transactions in code, using PlatformTransactionManager, and either commit them or roll back after the call to JpaTemplate.execute(JpaCallback).
I have noticed a few places in this area of our code where we are not doing this for reads, however, and simply call JpaTemplate.execute(JpaCallback) without wrapping in a transaction. I am wondering what the dangers are of this. I appreciate that a transaction must be being created, as no database query can be run without a transaction, but since nothing in our code attempts to commit, will something potentially be holding on to resources?

Categories