JPA / JTA / #Transactional Spring annotation - spring

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.

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

Spring boot , Spring data JPA concurrent access

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.

is it possible to have conditional #Transient field?

Let's say if I have an Entity named person with lots of information including SSN. When other user query this person, I want to show a 'lite' version of person Entity. I could've done so by annotating SSN with #Transient, but that means the person himself would not get this field too. Is it possible to reuse the same Entity but return two different json to client? I'm using spring boot.
First of all #Transient just means that the value, the SSN in your case, won't be persisted to the database.
As for your problem annotations are static and cannot be applied dynamically.
You have 2 Options:
Define a new View class for your user.
Look at JacksonJsonViews

Combine DAO and Entity in Spring and Hibernate

I was wondering if it is possible to combine DAO and Entity in a single class. e.g.
In rails
If I have table named user then there will be one ActiveRecord User and by using that class I can access access Methods related to DB and user i.e. it has both methods user.name (accessing object properties) and user.save / User.get_all methods (managing DB interactions) in the same class
In Spring/Hibernate Configuration
I have two things: DAO and Entity
Entity: I have User class that is an entity and is mapping Table as POJO, so that I can access methods related to a single user e.g. user.getName()
DAO: I have a DAO in which there are DB interactions e.g. userDAO.save(user) and userDAO.get(id).
Question:
I was wondering if I can create single User class and define User properties and getter/setter inside along with DB interactions so that I can single class as both, i.e. user.getName() (as POJO) and User.get(id)/user.save() (as DAO).
Is this method possible, and why are the complications I might run into, if I start with this approach?
it's called Active Record Pattern . Here is article about topic for JPA . Active Record Pattern . and example https://github.com/ActiveJpa/activejpa
Is this method possible, and why are the complications I might run into, if I start with this approach?
it's :
Cohesion & Coupling
if it's real project , it might become problem to support it
when you have 20 entities it's difficult to decide where to put method into what entity , and also find method that you need as it might be in many places
when you don't use active record pattern you can share entity with web layer , with active record entity can't be Serializable.
code become bigger and bigger

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.

Resources