Best Practises of #Repository in Spring boot framework - java

I have a Spring boot application which has a UserRepository but I have not annotated that repository with #Repository but still my application works fine.
Why #Repository annotation is optional in Spring boot and what is the best practise that should we annotate it or not in repository classes.

It is working because spring will scan the class path and identify given class is repository (DAO) based on the imports, when use #Repositary spring context know how to handle expections like re-throw to pre defined methods ..etc, and also this annotation help readability of the code.

For #Repository annotation even if you haven't mentioned Spring recognizes the repositories by the fact that they are extending Repository interfaces like JPARepository or CrudRepository.
So, it's not mandatory to mention annotation, you can check in your code whether you have mentioned #EnableJpaRepositories("packages") above Main class or not. That might also be one of the reasons why it is working.
As per best practices for annotations, they have a purpose to fulfill, #Repository is important from a database connection perspective, where it has lots of proper exceptions throw, or pre-defined methods.
If you do not use the proper annotations, you may face commit exceptions overridden by rollback transactions. You will see exceptions during the stress load test that is related to roll-back JDBC transactions.
For more clarity have a look at this post

I assume you have somewhere implicitly or explicitly a EnableJpaRepositories annotation which scans all Spring repositories and your repositories are extending CrudRepository or other Spring Data base classes.
The annotation is only needed when defining you own repositories without using Spring Data mechanism. Note, that Repository is just a special Component, latter should also do it to have DI enabled, so this is more for better recognizing the purpose of the class.

#Repository is used to indicate interface that extends a jpa repository, for example. Notice in the example below, the interface extends the Beer class and the BeerQueries query interface.
package com.algaworks.brewer.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.algaworks.brewer.model.Beer;
import com.algaworks.brewer.repository.helper.beer.BeersQueries;
#Repository
public interface Beers extends JpaRepository<Beer, Long>, BeersQueries {
}

Related

When to use dependency Injection in spring mvc?

I am working on a Spring MVC project where I am dealing with different types of services,Repositories i.e classes annotated with #Service and #Repository. I am confused with a couple of questions:
When to use #AutoWired annotation?
I have seen various repositories using this:
CourseRepository crepo=new CourseRepository();
and I have seen this also
#AutoWired
private CourseRepository crepo;
Which one of the above options should be used to get an instance of
repository in Service class?
Can I use #AutoWired for classes which are not annotated with #Repository or
#Service?
I am a beginner in this java world.Any help will be highly appreciated.
Thanks
You use new for data objects, which in most modern architectures are passive (they're not "active records"). Everything else is a service object, and you should inject those. (The one place that you do use new is with an #Bean method, which is a "factory" that creates the service object; in this case you normally pass the dependencies as method parameters.)
Note that it is recommended to use constructor injection instead of field injection; it makes your code easier to test, and it eliminates the possibility of certain kinds of errors. In fact, if using constructor injection, it's not required to have any Spring annotations in your service classes at all; beans can be registered using #Import instructions or #Bean methods on a configuration class.
You should #Autowire the dependencies instead of instantiating it yourself. Doing so, service and repo layer will be loosely coupled. Moreover, a mock repository can be easily injected in service's JUnit test class if dependency is autowired. To conclude, use below:
#Autowired
private CourseRepository crepo;
A class not annotated with any of below stereotype annotations will not be in Spring's IoC (Inversion of Control) container. Hence, no point in autowiring in a class that is not annotated with any of below annotations.
#Component, #Controller, #Service, #Repository
Dependency injection means that the framework is the one who handles the classes instantiation and the object of that class is going to be injected (thanks to #Autowired annotation) in the class where you need it. In other words, you do not need to instantiate service and repository classes by yourself using new operator, you just need to tell the framework that those classes need to be injected and that's why you use #Autowired annotation.

How can I do CRUD operations through CrudRepository in Spring?

I'm working with PostgresSQL and I have the following interface:
#Repository
public interface ExampleRepository extends CrudRepository<ExampleEntity, Long> { }
Then I try to get the bean:
ExampleRepository repository = ctx.getBean(ExampleRepository.class);
Of course, I can't do that, because there's no implementation and eventually I get
NoSuchBeanDefinitionException: No qualifying bean of type 'ExampleRepository'
I know this is a wrong approach, but since I'm not enough experienced, I've got no idea how I can communicate with my database. Any example I searched only explained how to implement services & controllers in order to interact with db through Browser. But I want to do CRUD operation inside the java code.
Could anyone explain it to me? Any related sources would also be fine.
I am not sure how you are getting context (ctx) here.
But the common approach is #Repository is not needed instead, #EnableJPARepositories should be used in the #Configuration file. Then use #Autowired to inject the repository into your service class (where you want to execute operation from your repository bean)
You can refer below link for more details
https://mkyong.com/spring-boot/spring-boot-spring-data-jpa/
You don't need to create bean. It will created by the spring framework because you annotated your interface as #Repository .You need only #Autowired in your service class or where do you want to use this reference.
#Autowired
private ExampleRepository exampleRepository;

Java + Micrometer #Timed annotation + Spring reactive #Repository possible?

Small question on the #Timed annotation from Micrometer, and how to use it with a reactive #Repository from Spring please.
I have a #Repository interface which is very straightforward, not even custom queries.
#Repository
public interface MyRepository extends ReactiveCassandraRepository<MyPojo, String> {
Here the example is with reactive Cassandra, but any reactive repository will do.
I would like to time the execution of the default methods, the save, findById, findAll, basically, all the straightforward methods a #Repository offers.
By time, I mean the real time taken to insert the data or to retrieve the data.
(This is particularly useful to see the read and write performance over time, under high load, etc...)
Hence, I tried with great hope:
#Repository
#Timed("mysupertimer")
public interface MyRepository extends ReactiveCassandraRepository<MyPojo, String> {
But sadly, it is not working.
Just to avoid confusion, it is not working for the repository methods.
I have #Timed in my #Controller layer, and different places of #Service layer, I see all the other metrics fine.
Also, I am really hoping for an answer on annotating the #Repository please. I understand I can just #Timed "all the places in my project calling the repository", but I have 300 calls to repositories and will need to explain to any future contributor to also annotate his calls.
A solution directly on the #Repository layer would be amazing.
Many thanks!
It is now possible with the latest version of SpringBoot 2.5.0
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes#timed-metrics-with-webflux

Using repository annotation when implementing JpaRepostiory in Spring

I'm not sure if I understand it correctly so want to clarify.
If I want to create a repository for my entity eg.:
public interface BookRepository extends JpaRepository<Book, Id> {}
Should I annotate it with #Repository? According to this question #Repository annotation translates exceptions from SQL to persistence ones but doesn't JpaRepostiory already do that? What's the best practice - to annotate or not?
While using JpaRepository you don't need to annotate the interface with #Repository
It is just an interface and the concrete implementation is created dynamically as a proxy object by Spring and the JDBC Exceptions are handled there.
You need to use #Repository when you create a Custom DAO, so that spring creates a bean and handles the exception properly.
You need to annotate it with #Repository so spring knows it should instantiate that class as a bean. The #Component, #Service and #Repository annotations all serve the same purpose in that regard. #Repository narrows the scope to a service that specifically deals with obtaining and storing data.

Spring Data CrudRepository and Transactions

I'm trying to implement transactions on a CrudRepository Interface. I'm a beginner with this and my current problem is that when receiving a lot of requests from different clients, I'm sometimes getting a duplicate.
To avoid that I wanted to use SQL Transactions and their implementation with Spring but I'm unable to get it working.
Here is how I've tried to do it :
#Repository
#EnableTransactionManagement
#Transactional
public interface ApplicationPackageDao extends CrudRepository<ApplicationPackage, Long> {
/**
* Find if a record exists for this package name ,
* #param packageName
* #return
*/
#Transactional
ApplicationPackage findByPackageName(String packageName);
}
However it doesn't seem to work.
I tried to add the #Transactionnal annotations earlier in the Java methods I'm calling but I can't get it working either.
How am I supposed to work with transactions on CrudRepository ?
Or am I using completely the wrong thing?
In addition to crm86's answer some more notes to the #Transactional annotation:
It seems to be best practice to annotate the entry points into your application (e.g. your web controller methods or the main method of a scheduled batch). By using the annotation attribute TxType you can ensure constraints/conditions in methods which are located deeper in your application (e.g. TxType.MANDATORY would throw if no trx-context is running, etc.).
The #Transactional annotation has only an effect if the class is loaded as spring bean (e.g. #Component annotation at class level).
Remember that only RuntimeException's lead to a rollback. If you want a checked Exception leading to a rollback you have to enumerate each such Exception by using the attribute rollbackOn.
The annotation at class level is valid for all public methods of this class. Method level annotations override those at the class level. The repeated annotation in your example above (first at class level, then at method level) has no effect.
What I suggest:
Check your context and configuration classes with #Configuration annotation. From the documentation:
The #EnableTransactionManagement annotation provides equivalent
support if you are using Java based configuration. Simply add the
annotation to a #Configuration class
#EnableTransactionManagement and only looks
for #Transactional on beans in the same application context they are
defined in
Then you could use #Transactional in your service even in a method
Hope it helps

Categories