I'm learning about Spring Boot and JPA, Spring Data Rest, H2 database and I have found a tutorial. I try to understand it and it is an easy example but I don't understand something. Why isn't it necessary to put @Repository
or @Component
in the AlienRepo class?
The repo object is injected in the AlienController class, and I know from previous tutorials that you need to use @Component
or @Repository
. I thought that it is mandatory to use this annotation.
The controller:
package com.dgs.springbootjpa.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.dgs.springbootjpa.dao.AlienRepo;
import com.dgs.springbootjpa.model.Alien;
@Controller
public class AlienController {
@Autowired
AlienRepo repo;
@RequestMapping("/")
public String home() {
return "home.jsp";
}
@RequestMapping("/addAlien")
public String addAlien(Alien alien) {
repo.save(alien);
return "home.jsp";
}
}
The POJO:
package com.dgs.springbootjpa.model;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Alien {
@Id
private int aid;
private String aname;
public int getAid() {
return aid;
}
public void setAid(int aid) {
this.aid = aid;
}
public String getAname() {
return aname;
}
public void setAname(String aname) {
this.aname = aname;
}
@Override
public String toString() {
return "Alien [aid=" + aid + ", aname=" + aname + "]";
}
}
The dao interface:
package com.dgs.springbootjpa.dao;
import org.springframework.data.repository.CrudRepository;
import com.dgs.springbootjpa.model.Alien;
public interface AlienRepo extends CrudRepository<Alien, Integer> {
}
You can see that in the AlienRepo interface there is not @Repository
or @Component
and the code is working successfully.
Thank you!
Update---------------------------------------------
I want to fetch data from database and I add the below code. I want to ask you why @RequestParam isn't mandatory? If I delete the @RequestParam the app is working successfully.
@RequestMapping("/getAlien")
public ModelAndView addAlien(@RequestParam int aid) {
ModelAndView mv = new ModelAndView("showAlien");
Alien alien = repo.findById(aid).orElse(new Alien());
mv.addObject(alien);
return mv;
}
Did you notice, CrudRepository has @NoRepositoryBean annotation and this annotation makes CrudRepository an intermediate interface. An intermediate interface is basically adds general functionality for your derived repositories.
If any class annotated with @NoRepositoryBean
Spring Data does not create instances at run-time. Because it's intermediate class and it's created to add functionality for the derived class.
If you extend an interface that has @NoRepositoryBean
and your derived interface doesn't have @NoRepositoryBean
Spring knows that you are trying to use that functionality in your real Repository interface so adding @Repository annotation is verbose.
Edit: Why @RequestParam isn't mandatory?
From the official documentation you can see "Controller method argument" table, the last row of the table says:
Any other argument :
If a method argument is not matched to any of the above, by default it is resolved as an @RequestParam if it is a simple type, as determined by BeanUtils#isSimpleProperty, or as an @ModelAttribute otherwise.
So if you omit annotation for "Controller Method Argument" and you don't write something like @MatrixVariable, @PathVariable or @RequestParam.
It's default a @RequestParam
.
@Component
and @Repository
can be used on classes to use them as Spring Beans. However, AlienRepo
is not a class, it's an interface which extends a Spring Data interface. Spring Data doesn't use annotations, it detects the interfaces by scanning the classpath and looking at the hierarchy of interfaces to see if a Spring Data interface is extended. If this is the case, it creates an implementation for each interface during runtime, which is then added to the application context as Spring Bean. That's why you don't need any annotations on a Spring Data interface.
Your @SpringBootApplication
brings in the effect of @EnableAutoConfiguration
annotation:
@EnableAutoConfiguration
public @interface SpringBootApplication
This annotation will guess and auto configure beans.
Auto-configuration for Spring Data's JPA Repositories. Activates when there is a bean of type DataSource configured in the context, the Spring Data JPA JpaRepository type is on the classpath, and there is no other, existing JpaRepository configured.
Once in effect, the auto-configuration is the equivalent of enabling JPA repositories using the EnableJpaRepositories annotation.
This configuration class will activate after the Hibernate auto-configuration.
public class JpaRepositoriesAutoConfiguration {
}
When you add data-jpa dependency, JpaRepositoriesAutoConfiguration
is triggered and bring effect of @EnableJpaRepositories
annotation to your app
Your repository then auto-configured:
Spring Data repositories usually extend from the Repository or CrudRepository interfaces. If you use auto-configuration, repositories are searched from the package containing your main configuration class (the one annotated with @EnableAutoConfiguration or @SpringBootApplication) down.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With