Spring boot , Spring data JPA concurrent access - spring-boot

I am trying to create a Restful API with Spring boot and Spring data JPA to do the CRUD operations. The database will be Oracle relational database.Now for concurrent access , If we only use spring transactions using #Transactional, will that serve our purpose of concurrent CRUD operations.
I see there are JPA Optimistic and pessimistic locking strategy version column. My specific question is , for concurrent CRUD operations do we need both Spring transactions and JPA locking strategy? OR only configuring Spring transactions accordingly will be sufficient?

Try to start with the following simple approach that IMO will be suitable in many cases: Optimistic locking with Spring Retry.
1) Add version property annotated with #Version to your entities (you can do it in base abstract entity class, for example, to simplify the process):
#Entity
public class MyEntity {
#Id
#GeneratedValue
private Long id;
#Version
private Long version;
// other stuff
}
In this case when you, for example, will update your entity then Hibernate will use the current value of version property in condition clause of update query, and increment this value to store the entity with it. For example this code of some service:
#Transactional
public Optional<MyEntity> update(Long id, MyEntity source) {
return myEntityRepository
.findById(id)
.map(target -> mapper.updateEntity(source, target));
}
will generate the following SQL queries:
1. select * from my_entities where id = ?;
2. update my_entities set ..., version = <version value from query #1> + 1 where id = ? and version = <version value from query #1>;
So if another concurrent process manages to update this entity first, then your method fails with an exception (OptimisticLockException).
2) To manage to exceptions in that method, add #Retryable annotation to it (and #EnableRetry annotation on your config or application class):
#Retryable(maxAttempts = 2)
#Transactional
public Optional<MyEntity> update(Long id, MyEntity source) {
// ...
}
In this case, if an exception rises in that method it will be called again in a new transaction to repeat the operation.
Additional info:
Optimistic Locking in JPA
Guide to Spring Retry
My Spring Retry demo

Optimistic lock is default strategy of JPA. Optimistic locking is can be used for most of the applications. Optimistic lock is much more easier and efficient. Pessimistic lock need to be used in cases like, where you need to know Collision before committing your transaction.
So you do not need to configure a locking strategy.

Related

Spring Data JPA + Bytecode Enhancement

Is it possible to load #*ToOne attributes eagerly using JPA interface(Entity Graphs) which are set lazy using #LazyToOne , #LazyGroup in the parent entity class and enabled bytecode enhancement ? I am trying to load such attributes eagerly using entity graph but it is firing another query for such #*ToOne attributes when an parent entity is queried.
Trying to have another way to override static fetch type in entity classes including #LazyToOne which was added with bytecode enhancement.
Using Spring 5.1.3 , Spring JPA 2.2 , Hibernate 5.4.19
Update : Data JPA is working as expected and i could see joins for the attributes which i am trying to fetch eagerly but those lazy attributes are not being initialised with the join query response and hibernate causing each query on referencing attributes which were annotated with #LazyToOneOption.NO_PROXY and was already fetched eagerly using entity graph in my repository.
How can i avoid this second select which is not even required since i got the that data eagerly from entity graph in JPA respository ??
Any help would be highly appreciated.
Entity Graphs just like Hibernate fetch profiles apply regardless of what annotations you have on the association. If it does not, maybe there is a bug in Spring Data or maybe even Hibernate. It's probably best if you create a new JIRA issue with a test case reproducing the problem.
Having said that, I think this is the perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
An example DTO model could look like the following with Blaze-Persistence Entity-Views:
#EntityView(User.class)
public interface UserDto {
#IdMapping
Long getId();
String getName();
Set<RoleDto> getRoles();
#EntityView(Role.class)
interface RoleDto {
#IdMapping
Long getId();
String getName();
}
// Other mappings
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
UserDto a = entityViewManager.find(entityManager, UserDto.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Delete and add data to the mysql database with spring hibernate 4 in single transaction

I want to update entire database in mysql database through my spring application (hibernate 4, spring 1.4.5).
Steps:
1. delete entire data from DB
2. update new record
3. rollback if 1 or 2 fails
How do I achieve with #Transactional?
I have used org.springframework.transaction.annotation.Transactional and propagation = MANDATORY.
But I can see the table get deleted while it is still in the same Transactional Method.
#Transactional(propagation = Propagation.MANDATORY)
private void testMtd(List<Data> data){
repository.deleteAll();
repository.save(data);
}
How can I overcome this problem?
Annotating the Application started class (main class) with #EnableTransactionManagement will work.

How do I execute named queries from a JPA EntityListener?

I have a requirement to set a date_updated value in my database for each row when that row is updated. Let's call the entity that I'm working with Order, which has a corresponding orders table in the database.
I've added the date_updated column to the orders table. So far, so good.
The #Entity Order object that I'm working with is provided by a third party. I do not have the ability to modify the source code to add a field called dateUpdated. I have no requirement to map this value to the object anyway - the value is going to be used for business intelligence purposes only and does not need to be represented in the Java entity object.
My problem is this: I want to update the date_updated column in the database to the current time each time an Order object (and its corresponding database table row) is modified.
Constraints:
We are using Oracle, Spring, JPA and Hibernate
I cannot use Oracle triggers to update the value. We are using a database replication technology that prevents us from using triggers.
My approach thus far has been to use a JPA EntityListener, defined in xml, similar to this:
<entity-mappings xmlns="....">
<entity class="com.theirs.OrderImpl">
<entity-listeners>
<entity-listener class="com.mine.listener.OrderJPAListener" />
</entity-listeners>
</entity>
</entity-mappings>
My listener class looks like this:
public class OrderJPAListener {
#PostPersist
#PostUpdate
public void recordDateUpdated(Order order) {
// do the update here
}
}
The problem I'm having is injecting any sort of persistence support (or anything at all, really) into my listener. Because JPA loads the listener via its methods, I do not have access to any Spring beans in my listener class.
How do I go about injecting an EntityManager (or any Spring bean) into my listener class so that I can execute a named query to update the date_updated field?
How do I go about injecting an EntityManager (or any Spring bean) into
my listener class so that I can execute a named query to update the
date_updated field?
As noted above JPA 2.1 supports injecting managed beans to an Entity Listener via CDI. Whether or not Spring supports this I am not sure. The folloiwng post proposes a Spring specific solution.
https://guylabs.ch/2014/02/22/autowiring-pring-beans-in-hibernate-jpa-entity-listeners/
A possible alternative approach would be however to override the SQL generated by Hibernate on an update which is possible as detailed below.
https://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/querysql.html#querysql-cud
This would be straightforward if you had the source as you would just need to add the #SQLUpdate annotation and tag on the additional date_update column. As you don't however you would need to look at redefining the metadata for that Entity via an xml configuration file and defining the sql-update statement as outlined above:
https://docs.jboss.org/hibernate/stable/annotations/reference/en/html/xml-overriding.html#xml-overriding-principles-entity
Since JPA 2.1 Entity Listeners are CDI managed. Have you tried using #PersistenceUnit annotation? Are you using JTA transaction type?
Otherwise you could use Persistence.createEntityManagerFactory within the Listener class to retrieve the Persistence Context.

JPA / JTA / #Transactional Spring annotation

I am reading the transaction management Using Spring framework. In first combination I used Spring + hiberante and used Hibernate's API's to control the transaction (Hibenate API's). Next, I wanted to test using #Transactional annotation, and it did work.
I am getting confused on:
Do JPA , JTA, Hibernate have their "own" way of transaction
management. As an example, consider if I use Spring + Hibernate, in
that case would u use "JPA" transactions?
Like we have JTA, is it true to say we can use Spring and JTA to
control transactions?
The #Transactional annotation, is that specific to Spring
Framework? From what I understood, this annotation is Spring
Framework specific. If this is correct, is #Transactional using
JPA/JTA to do the transaction control?
I do read online to clear my doubts, however something I don't get direct answer. Any inputs would be great help.
#Transactional in case of Spring->Hibernate using JPA i.e.
#Transactional Annotations should be placed around all operations that are inseparable.
So lets take example:
We have 2 model's i.e. Country and City.
Relational Mapping of Country and City model is like one Country can have multiple Cities so mapping is like,
#OneToMany(fetch = FetchType.LAZY, mappedBy="country")
private Set<City> cities;
Here Country mapped to multiple cities with fetching them Lazily.
So here comes role of #Transactinal when we retrieve Country object from database then we will get all the data of Country object but will not get Set of cities because we are fetching cities LAZILY.
//Without #Transactional
public Country getCountry(){
Country country = countryRepository.getCountry();
//After getting Country Object connection between countryRepository and database is Closed
}
When we want to access Set of Cities from country object then we will get null values in that Set because object of Set created only this Set is not initialize with there data to get values of Set we use #Transactional i.e.,
//with #Transactional
#Transactional
public Country getCountry(){
Country country = countryRepository.getCountry();
//below when we initialize cities using object country so that directly communicate with database and retrieve all cities from database this happens just because of #Transactinal
Object object = country.getCities().size();
}
So basically #Transactional is Service can make multiple call in single transaction without closing connection with end point.
Hope this will helpful to you.

Spring Transactional annotation, Hibernate and persist

I've a misunderstanding of Spring #Transactional annotation and persist. I am using Spring 3.1, with JPA and Hibernate. I thought that persist meant, add the entity to the persistence context (but don't execute any query until commit or flush), and that the #Transactional annotation meant, wrap the method with a transaction.
However, in this short example, when the execution pointer reaches persist, it fails with an exception, since name can't be null (db constraint).
import javax.persistence.EntityManager;
#PersistenceContext
private EntityManager entityManager;
#Transactional
public void test() {
Brand brand = new Brand();
entityManager.persist(brand);
brand.setName("test");
}
If I swap setName() and persist(), everything works. However, I don't understand why the other way around doesn't since I thought that any query would be built and executed at the end of the method.
Can someone please explain?
In JPA, once an object passed to persist() it becomes "managed", as part of becoming managed JPA implementation must generate an id for the persistent object.
If id generation is based on auto-increment (GenerationType.IDENTITY), then an insert statement needs to be issued to the db to get and assign the key. When the id generation is based on sequence / table then ids are managed and assigne by the JPA Implementation managed id pools, in which case a straight insert is not a requirement.
Having an object is passed to persist() and has become managed, any changes to it is persistent fields must be flushed to the database at the and of the transaction. In your case if the id generation is Identity then an insert must be followed an update. If the id generation is some other method then, a single insert statement is sufficient. If the transaction is rolled back, no SQL should be get sent to database at all.
This is the implementation in Batoo JPA.
Hope this makes sense.
Its committed at end of method thanks to transactional annotation. But the new record is created on persist, and any exceptions can be thrown.
Before the end of method it can still be rolled back; I normally annotate with rollback for exception.
The persist executes the "insert" query. The transacation annotation is just for starting a transaction and if a exception occurs roll back the transaction.

Resources