What happened before?
Part 1: Spring Data Commons
Part 2: Spring Data JPA
After looking at the Spring Data Commons project in the first part of this blog series, today I’m going to introduce you to the sub project Spring Data JPA .
JPA
Being a part of JEE stack, JPA is a standard API to persist Java objects into relational database systems. With the JPQL query language, database queries can be written independent of a specific SQL dialect. So understanding Spring Data JPA requires at least a basic knowledge of the JPA API .
Spring Data JPA
Based on Spring’s standard JPA Support , Spring Data JPA further simplifies writing JPA repositories (and much more). Usually one or more parameters have to be set before executing a JPQL query. To do so, the developer writes boilerplate code like this:
1@Entity
2@NamedQuery( name="myQuery", query = "SELECT u FROM User u where u.fullName = :fullName" )
3public class User {
4...
5}
6
7@Repository
8public class ClassicUserRepository {
9
10 @PersistenceContext EntityManager em;
11
12 public List<User> findByFullName(String fullName) {
13 TypedQuery<User> q = getEntityManger().createNamedQuery("myQuery", User.class);
14
15 q.setParameter("fullName", fullName);
16
17 return q.getResultList();
18 }
19 ...
This can be slightly reduced by using the fluent interface of a TypedQuery
…
1@Repository
2public class ClassicUserRepository {
3
4 @PersistenceContext EntityManager em;
5
6 public List<User> findByFullName(String fullName) {
7 return getEntityManger().createNamedQuery("myQuery", User.class)
8 .setParameter("fullName", fullName)
9 .getResultList();
10 }
11 ...
… but still you are implementing a method that calls setters and executes the query for each and every single query. With Spring Data JPA the same query comes down to the following piece of code:
1package repositories;
2
3public interface UserRepository extends JpaRepository<User, String> {
4
5 List<User> findByFullName(String fullName);
6}
The basic idea is to derive all information that is required to execute a query from the signature of method declared in an interface(!). At runtime Spring injects a corresponding implementation that creates and executes the query via the JPA criteria API. This way, a very large subset of queries within a project can be written very fast and concise. The pattern can be combined with the common sorting and pagination features:
1public interface UserRepository extends JpaRepository<User, String> {
2
3 List<User> findByFullName(String fullName, Sort sort);
4
5 List<User> findByFullName(String fullName, Pageable paging);
6}
With Spring Data JPA, JPQL queries don’t have to be declared as @NamedQuery
s in the class file of the corresponding JPA entity. Instead a query is an annotation of the repository method(!):
1@Transactional(timeout = 2, propagation = Propagation.REQUIRED)
2 @Query("SELECT u FROM User u WHERE u.fullName = 'User 3'")
3 List<User> findByGivenQuery();
I really like this approach. The query is located in the place where it is executed and does not pollute the JPA entity itself. Separation of Concerns (SoC) at its best. A drawback is that you have to use a new Spring annotation @Query
. Why didn’t they allow the use of @NamedQuery
annotations?
A nice bonus is the validation of JPQL queries when the application context is assembled. This way JPQL syntax errors are detected as early as possible. Usually these errors are detected at query execution time.
Example
I provide a maven project holding all example source code at Github . The examples use OpenJPA as a JPA provider and the RDBMS HyperSQL DB . The unit test jpa.JpaRepoTest
is a good place to start.
The most important configuration part is the one that defines the package structure of our repositorie interfaces to be automagically JPA-ified:
1<jpa:repositories base-package="jpa"/>
If your are using more than one EntityManagerFactory
, you have to specifiy which one should be used by your repositories.
Is there more?
Yes. As I said in the first part of this blog series, I’m just presenting some choosen aspects of Spring Data JPA. For a complete list of features, please check the project’s homepage .
What’s next?
Expect upcoming blog posts on Spring Data MongoDB or Spring Data Neo4J .
More articles
fromTobias Trelle
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
More articles in this subject area
Discover exciting further topics and let the codecentric world inspire you.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Tobias Trelle
Software Architect
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.