In general you are correct.
Repository is a design pattern similar to DAO (Data Access Object) in the sense that its goal is to abstract access to data in a generic way from its model. The difference is that the Repository seeks to represent the data as a collection of elements, even remembering a Collection
.
The Spring Data Jpa project facilitates implementation of the standard Repository through AOP (Aspect Oriented Programming - aspect-oriented programming).
Using only one interface, Spring will dynamically "generate" the implementation of data access methods. Extend the interface JpaRepository
is optional, but the advantage is it already comes with several of generic CRUD methods and you don’t need to reset them all.
At first it might be a little weird to use this Spring project. Who does not know AOP and how Spring Data works will waste time looking for the implementation of interfaces.
Creating new methods simply via 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 names of the methods means that it will be a query method.
What comes next is as an expression that defines which attributes will be used as filters. In the first example, findByNome
, means, search by 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
.
In addition, the special parameter of the type Pageable
says the result will be paged. Note that the return method is a "customer page".
See the documentation on cherishing for more details.
Alternatively, you can specify any JPA or native query through the @Query annotation. See documentation.
Example of JPA query:
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.firstname like %?1")
List<User> findByFirstnameEndsWith(String firstname);
}
Example of native query:
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?0", nativeQuery = true)
User findByEmailAddress(String emailAddress);
}
Customizing the Spring Data Jpa
There are basically two ways to further customize the Spring Data JPA:
Creating a specific implementation
If for only one case you really 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 in the same package
ClienteRepositoryImpl
implementing this interface.
- Interface
ClienteRepository
extend the interface ClienteRepositoryCustom
See the documentation.
Creating a "generic interface"
If you have methods that you want to have in all repositories, but that are not present in the interface JpaRepository
, you can create a generic interface with these methods and have your repositories extend this interface.
Replacing the Jparepository implementation
Well, all magic has a trick behind the scenes. There is, yes, an implementation of all this and you can extend it conforms your goals.
I myself did this 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 greatly lengthening the content. So I’m going to leave the link to one of the articles I used to make the implementation is Customizing Spring Data JPA Repository.
On the one hand, create your extended version of JpaRepository
it’s not very complicated, but I suggest you try to address specific issues using the more specific approaches already mentioned. Think twice before creating or overwriting methods that affect all your classes.
thanks for your reply, but during a reading a doubt caught my attention even of other material I read, in the material said that automatically the
Spring
would implement the methods for me through the class attributes, correct? If yes, in my example does not occur.– Macario1983
@Macario1983 I did not understand what you meant by "in my example does not occur". Anyway, just to clarify, if you have a JPA entity
Cliente
with an attributeString nome
and create a signatureCliente findByNome(String nome);
, Spring Data Jpa can create a query like this:select c from Cliente c where nome = :nome
.– utluiz
@Macario1983 but you only see it at the time of execution.
– utluiz
in my example, would be the test code in Eclipse , as I was seeing in this tutorial, if I didn’t get it wrong, automatically by the attributes of the model class would be created search methods (
findBy
) with each attribute of the class, therefore my comment. http://www.baeldung.com/2011/12/the-persistence-layer-with-spring-data-jpa/– Macario1983
@Macario1983 No, that’s not what happens. Spring does not automatically create methods for cadas attribute, because that would be a great waste. It creates methods according to the signatures that are in the interaface. What is described in the last topic of my answer is that I created a generic search method based on a map. If the map has the input
nome = "José"
oridade = 30
, then the query would have the following filter:where nome like 'José%' and idade = 30
. However, I had to do this implementation manually.– utluiz
and you implement without DAO? And how good it brings you from your implementation?
– Macario1983
In the project I mentioned, I don’t have the DAO layer. The layers are: Controller (JSF Managedbeans), Service (spring Beans business rules) and Repository (Spring repositories). A great advantage of Repository is not to waste time implementing each DAO method (which is most often a copy of each other). This prevents a developer from introducing incorrect database access logic (forgetting to close connections, setting incorrect parameters, etc.). However, the same effect could be achieved by creating generic Daos, which you extend and get the implementation of basic methods.
– utluiz
@Macario1983 I forgot to quote you in the previous comment.
– utluiz
The link you passed the author does a few more things that gets really complicated so that this starting to understand, some statements of objects in the class, but it turns out that the
EntityManager
plays the role ofHibernateSessionFactory
that we created right? This kind of approach as it stands in relation to the patternOpenSessionInView
? Or this pattern should use Spring’s own?– Macario1983
@Macario1983 O
EntityManager
is equivalent toHibernateSession
, but that is part of the JPA specification and the other is specific to Hibernate. In general, for new implementations, it is better to use JPA standard. That doesn’t change much aboutOpenSessionInView
, but this is a pattern unsaved. I always try to wear something like Session per request (a session/entitymanager/connection per request.– utluiz
I ask you about the pattern you wear instead of the
OSIV
because while I created the TCC program, using as a basis the company system, I saw that at all times it was called the classOpen Session In View
, and I had another problem, that the transactions were opened at the request levelHTTP
, because I say this, because my program had as purpose either the user insert a collection of files or the files downloaded directly from the servere-mail
, when the transaction was taking place at the level ofe-mail
from the system, that this function was automated, transaction was not initialized.– Macario1983
In fact,
EntityManager
is equivalent toSession
of Hibernate, while aEntityManagerFactory
of JPA is equivalent toSessionFactory
hibernate.– Rogério
@Roger That’s right. Thanks for the correction.
– utluiz