Spring Data Access - Spring Data JPA
In my previous blog post we discussed Spring Data. Spring Data JPA is project under this higher-level project. Spring Data JPA makes it easy to implement JPA (specification) based repositories. It is a data access abstraction.
Spring Data JPA can work with any JPA provider like Eclipse Link or Hibernate. With Spring or Java EE, we can even control transaction boundaries using the
Spring Data JPA gives a definition to implement repositories supported under the hood through the JPA specification, using the provider we define.
To define a data access object (DAO) we only need an interface extending Spring's
JpaRepository<T,K> like the following:
We've extended Spring's
JpaRepository interface. It's recommended to name the interface after the entity class it concerns. The only two details needed:
- Entity class name for database operations. In our case it's
- The data type of the primary key of our entity class. In our case it's
Spring scans our interface that extends this
JpaRepository interface. It auto-generates common CRUD, paging, and sorting methods at run time through a proxy object. We can add the
@Repository annotation, but it's optional because Spring will auto-detect this interface as a repository. Thanks to this interface, we can use method name queries as well as JPQL to access our data.
Instead of manually configuring a
DataSource like we did in JDBC, we can do so through dependency management. It consists of injecting a
DataSource bean into some kind of
EntityManagerFactory bean. For JDBC this isn't necessary because it only relies on the
We can autowire an instance of our
CustomerRepository into our service layer. With this instance we will use repository methods provided by the
Here's an example service implementation class invoking repository methods through the autowired repository:
We do this by extending the
JpaRepository like the following:
Pagination and Sorting
PagingAndSortingRepository<T,ID> is an interface that extends
CrudRepository<T,ID> which extends
Repository<T,ID>. In the example we saw above,
JpaRepository<T,ID> actually extends the
PagingAndSortingRepository<T,ID> so we get all its functionality.
Page<T> object provides the data for the requested page as well as more information like total result count, index, and more.
Sort instance we can describe the sorting order based on an entity property.
With these two methods we can now have pagination and sorted queries!
There are many approaches for querying for data inherited in the
- Query by method name
- Query creation using
- Query creation using
Also, if one or more query approach is in a Spring application there is an order of precedence:
- @Query (highest precedence)
- findBy methods
Let's say our application needed to perform an update on two tables in a database. There is a relationship between these tables. If the first table update fails, should we continue updating the other table?
If we want to maintain data integrity and consistency, the answer is no. Updating should be successful only if the update on both tables is successful. We achieve this by executing related database operations in a transaction scope.
Luckily, Spring provides a common transaction API. It works irrespective of underlying transaction technologies such as Hibernate, JDBC, JPA, or JTA. The
@Transactional annotation is used at either the class level (for all methods) or for individual methods. The Spring team recommends using
@Transactional in the service layer to enforce the databases to use transaction management.
Spring transactions support:
- Transaction isolation: The degree of isolation of this transaction with other transactions.
- Transaction propagation: Defines the scope of the transaction.
- Read-only status: A read-only transaction will not change any data. These can be useful for optimization in some cases.
- Transaction timeout: How long a transaction can run before timing out.