Using the JPA repository
Last Saturday I presented my CBT in college and saw that I need to improve the project presented. The system receives invoices in XML
format and handles them. I took as a basis the system in the company where I do internship. Primefaces, JSF, Spring IoC, Hibernate are used.
I then started reading some Googled stuff, left me maybe confused, but I'll let you know what I understood.
The repository would be a class to fetch information from the bank where the information was persisted. But in the case of JpaRepository
it provides the connection to a certain class of Model
with the possibility of persisting in the database.
Am I correct?
I read that this implementation is a good one, as DAO
is abstracted from the ORM
of the JPA. So there would be no need to implement a DAO
class.
I would like the idea of colleagues to know what is right in thinking and what is wrong.
And if using interface JpaRepository
is can I make an abstract class and then my classes implemented as a repository extend it? And work together with service
?
Would they have any example code or link?
2 answers
In general you are correct.
Repository Pattern
Repository is a design pattern similar to DAO ( Data Access Object) in that its purpose is to abstract data access generically from your model. The difference is that the repository seeks to represent the data as a collection of elements, even remembering a Collection
.
Spring Data JPA
The project Spring Data JPA facilitates the implementation of the repository standard through AOP (Aspect Oriented Programming).
Using only one interface, Spring will dynamically "generate" the implementation of data access methods. Extending the JpaRepository
interface is optional, but the advantage is it already comes with several of generic CRUD methods and you don't need to reset all of them.
At first it may be a little strange to use this spring design. Those who do not know AOP and how Spring Data works will waste time looking for the implementation of the interfaces.
Creating new methods simply through signatures is very easy. See this example:
@Repository
public interface ClienteRepository extends JpaRepository<Cliente, Long> {
Cliente findByNome(String nome);
Page<Cliente> findByCidadeAndEstado(Cidade cidade, Estado, estado, Pageable pageable);
}
At first we can ask: What does Spring do with it?
First the prefix findBy
in the method names means that it will be a query method.
What comes next is like an expression which defines which attributes will be used as filters. In the first example, findByNome
, means, search for the attribute nome
using the value passed in the first parameter. In the second example, the generated query will use an expression with the operator AND
considering the attributes cidade
and estado
.
Also, the special parameter of type Pageable
says that the result will be paged. Note that the method return is a "customers Page".
See the documentation on creating queries for more details.
Alternatively, you can specify either a JPA or native query using the @Query annotation. See documentation .
JPA query example:
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.firstname like %?1")
List<User> findByFirstnameEndsWith(String firstname);
}
Native query example:
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?0", nativeQuery = true)
User findByEmailAddress(String emailAddress);
}
Customizing Spring Data JPA
There are basically two ways to further customize Spring Data JPA:
Creating a specific implementation
If for only one case you even need to make an implementation of methods, it is possible. For this, if you have an interface ClienteRepository
:
- create an interface
ClienteRepositoryCustom
with the methods you want to implement. - create a class
ClienteRepositoryImpl
in the same package by implementing this interface. - make the interface
ClienteRepository
extend the interfaceClienteRepositoryCustom
See documentation .
Creating a "generic" interface
If you have methods you want to have in all repositories, but not present in the JpaRepository
interface, you can create a generic interface with these methods and make your repositories extend that interface.
Replacing the implementation of JpaRepository
Well, all magic has a behind-the-scenes trick. There is, yes, an implementation of all this and you can extend it according to your goals.
I did this myself in a recent project to allow a dynamic search using a map, where each map entry is automatically added to the search clauses.
I believe that describing the whole process is outside the scope of the answer, as well as stretching the content a lot. So I'll leave the link of one of the articles I used to do the implementation is Customizing Spring Data JPA Repository.
For one thing, creating your extended version of JpaRepository
isn't too complicated, but I suggest you try to solve specific issues using the more specific approaches already mentioned. Think twice before creating or overwriting methods that affect all of your classes.
A DAO is a design pattern that abstracts the data persistence. A repository is an abstraction of a collection of objects and their respective manipulation methods. The two can exist in the same project. A trinca DAO, repository and DTO (Data Transfer Object) can be considered a unit of Work (Unit of Work).
A formal definition of DAO has on Oracle's website: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html . a translator can help.
A general overview of JPA repository can be found here: http://workingonbits.com/2011/05/05/effective-pattern-for-data-access-with-jpa/.
The JPA repository is a special repository implementation, but note that the repository is concerned with exposing methods that manipulate collections, not Database operations such as DAO. No case from spring'S JPA repository, it sets out to do some things in automatic (search, insert, update), but still the focus is on manipulating items from a collection.
It may even be that the concepts get confused because there are people who implement a repository with a DAO face (for example, putting a method called Update()
in the repository). The correct thing, in the case of a fully integrated repository with a database, would be for the repository to update this so transparent.