Search code examples
mysqlspring-bootexceptionjavabeansautowired

Exception:Field studentRepository in com.example.demo.cotroller.StudentController required a bean of type 'com....Repository' that could not be found


I followed https://spring.io/guides/gs/accessing-data-mysql/#initial to satrt learning springboot with MySQL. And I met a bug as follows.

2021-09-23 01:28:31.193  INFO 1196 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication using Java 1.8.0_144 on DESKTOP-PFH9867 with PID 1196 (C:\Users\Admin\IdeaProjects\demo\target\classes started by Admin in C:\Users\Admin\IdeaProjects\demo)
2021-09-23 01:28:31.196  INFO 1196 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2021-09-23 01:28:33.014  INFO 1196 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-09-23 01:28:33.027  INFO 1196 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-09-23 01:28:33.027  INFO 1196 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.52]
2021-09-23 01:28:33.145  INFO 1196 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-09-23 01:28:33.146  INFO 1196 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1875 ms
2021-09-23 01:28:33.218  WARN 1196 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'studentController': Unsatisfied dependency expressed through field 'studentRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.repository.StudentRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2021-09-23 01:28:33.221  INFO 1196 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2021-09-23 01:28:33.242  INFO 1196 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-09-23 01:28:33.269 ERROR 1196 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field studentRepository in com.example.demo.cotroller.StudentController required a bean of type 'com.example.demo.repository.StudentRepository' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.example.demo.repository.StudentRepository' in your configuration.


Process finished with exit code 1

Obviously, the main problem is @Autowired in Controller. Therefore, I searched a lot of methods to deal with it. And I don't wanna add new code or new file. As the website said when the interface Repository is created, Spring automatically implements this repository interface in a bean that has the same name (with a change in the case — it is called userRepository). Therefore, I don't wanna add new code or file. I thought the issue is in my application.properties or the relative location of directories. But they don't work at all.

And my code is as follows.

DemoApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class  DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

Student.java

package com.example.demo.entity;

import javax.persistence.Entity;

// https://spring.io/guides/gs/accessing-data-mysql/

@Entity // This tells Hibernate to make a table out of this class
public class Student {
    // 2147483647
    private Integer studentID;

    private String name;

    private String department;

    private String major;

    public Integer getStudentID() {
        return studentID;
    }

    public void setStudentID(Integer studentID) {
        this.studentID = studentID;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public String getMajor() {
        return major;
    }

    public void setMajor(String major) {
        this.major = major;
    }
}

StudentController.java

package com.example.demo.cotroller;

import com.example.demo.entity.Student;
import com.example.demo.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller // This means that this class is a Controller
@RequestMapping(path="/api/v1/student") // This means URL's start with /demo (after Application path)
public class StudentController {
    // This means to get the bean called studentRepository
    // Which is auto-generated by Spring, we will use it to handle the data
    @Autowired
    private StudentRepository studentRepository;

    @PostMapping(path="/add") // Map ONLY POST Requests
    public @ResponseBody
    String addNewUser (@RequestBody Student student) {
        // @ResponseBody means the returned String is the response, not a view name
        // @RequestParam means it is a parameter from the GET or POST request

        studentRepository.save(student);
        return "Saved";
    }
}

StudentRepository.java

package com.example.demo.repository;

import com.example.demo.entity.Student;
import org.springframework.data.repository.CrudRepository;

// This will be AUTO IMPLEMENTED by Spring into a Bean called userRepository
// CRUD refers Create, Read, Update, Delete
public interface StudentRepository extends CrudRepository<Student, Integer> {
}

My directories are organized as follows.

java
|--com.example.demo
   |--controller
      |--StudentController.java
   |--entity
      |--Student.java
   |--repository
      |--StudentRepository.java
   DemoApplication.java   

SOLVED!

Finally, I found the true reason! I am too careless to follow the tutorial. It said Click Dependencies and select Spring Web, Spring Data JPA, and MySQL Driver. but I didn't click Spring Data JPA!

I recreated the project by selecting Spring Web, Spring Data JPA, and MySQL Driver in IDEA, and copied the files described in the question descrption, then the problem is solved.


Solution

  • Yes, you're right spring perform the repository configuration by their side but you have to inform to spring on which class you want to perform or include this functionality. For that you have to add @Repository annotation in your repository class.

    And One more thing for your knowledge. In any language structure is the essential part of any programming language. To understand it you always have to follow Best practices. Here you defined repository class directly in controller which is completely wrong. Controller is just for controlling in coming request and send response back to them. So, This kind of business logic always take place in your service class or DAOImpl class. Don't define to database object in other classes.

    In addition if you work with multiple Classes like User and Department and you want to perform any action only service to service communication take place not share repository object