Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't necessary @Repository for this Spring Boot web app?

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;
}
like image 605
elvis Avatar asked Aug 19 '18 13:08

elvis


Video Answer


3 Answers

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.

like image 180
Muhammed Ozdogan Avatar answered Oct 29 '22 18:10

Muhammed Ozdogan


@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.

like image 29
dunni Avatar answered Oct 29 '22 16:10

dunni


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.

like image 26
Mạnh Quyết Nguyễn Avatar answered Oct 29 '22 18:10

Mạnh Quyết Nguyễn