简体   繁体   English

Spring 引导 - 将存储库注入 Controller 抛出考虑在配置中定义类型为“Type”的 bean

[英]Spring Boot - Injecting Repository into Controller throws Consider defining a bean of type 'Type' in your configuration

I have a Spring/Boot REST controller which I inject a repository into like so:我有一个 Spring/Boot REST controller 我将存储库注入如下:

package com.example.schooltimetable.controllers;

import com.example.schooltimetable.models.entities.StudentEntity;
import com.example.schooltimetable.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin
@RequestMapping("student")
public class StudentController {

    private final StudentRepository studentRepository;

    @Autowired
    public StudentController(StudentRepository studentRepository) {
        this.studentRepository = studentRepository;
    }

    @RequestMapping(value = "/getAll", method = RequestMethod.GET)
    public Iterable<StudentEntity> getAllStudents() {
        return this.studentRepository.findAll();
    }
}

The problem I'm facing is that whenever i start my application it throws the following error:我面临的问题是,每当我启动我的应用程序时,它都会引发以下错误:

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

Description:

Parameter 0 of constructor in com.example.schooltimetable.controllers.StudentController required a bean of type 'com.example.schooltimetable.repository.StudentsRepository' that could not be found.


Action:

Consider defining a bean of type 'com.example.schooltimetable.repository.StudentsRepository' in your configuration.


Process finished with exit code 1

I faced this issue before when trying to find an Entity in another class, I fixed this by using the @ComponentScan() annotation in Application.java , however, it doesn't work to fix this issue.我在尝试在另一个 class 中查找实体之前遇到了这个问题,我通过使用Application.java中的@ComponentScan()注释解决了这个问题,但是,它无法解决这个问题。

My main application file looks like this:我的主应用程序文件如下所示:

SchoolTimetableApplication学校时间表申请

package com.example.schooltimetable;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan({
    "com.example.schooltimetable.controllers",
    "org.springframework.stereotype",
    "com.example.schooltimetable.repository",
})
public class SchoolTimetableApplication {
    public static void main(String[] args) {
        SpringApplication.run(SchoolTimetableApplication.class, args);
    }
}

And my repository looks like this: StudentRepository我的存储库看起来像这样:StudentRepository

package com.example.schooltimetable.repository;

import com.example.schooltimetable.models.entities.StudentEntity;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

@Repository
@Component
public interface StudentRepository extends CrudRepository<StudentEntity, Long> { }

The StudentEntity referenced in the repository:存储库中引用的 StudentEntity:

package com.example.schooltimetable.models.entities;

import com.example.schooltimetable.models.constants.StudentEntityConstants;
import com.example.schooltimetable.models.constants.TimetableEntityConstants;
import org.springframework.lang.NonNull;

import javax.persistence.*;
import java.util.UUID;

@Entity
@Table(name = StudentEntityConstants.TABLE_NAME)
public class StudentEntity {

    @Id
    @Column(name = StudentEntityConstants.ID)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = StudentEntityConstants.FIRST_NAME)
    @NonNull
    private String firstName;

    @Column(name = StudentEntityConstants.LAST_NAME)
    @NonNull
    private String lastName;

    @Column(name = StudentEntityConstants.REFERENCE)
    @NonNull
    @GeneratedValue(strategy = GenerationType.AUTO)
    private UUID reference;

    @OneToOne(targetEntity = TimeTableEntity.class)
    @JoinColumn(name = TimetableEntityConstants.REFERENCE)
    private TimeTableEntity timeTable;

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public UUID getReference() {
        return this.reference;
    }

    public void setReference(UUID reference) {
        this.reference = reference;
    }

    public TimeTableEntity getTimeTable() {
        return this.timeTable;
    }
}

And my POM file:还有我的 POM 文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>school-timetable</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>school-timetable</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
            <version>2.3.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Is there something I've done wrong?是不是我做错了什么? I'm very new to Spring/Boot.我对 Spring/Boot 很陌生。 An interesting note with this issue is that if I remove这个问题的一个有趣的注释是,如果我删除

@ComponentScan({
    "com.example.schooltimetable.controllers", <---- This
    "org.springframework.stereotype",
    "com.example.schooltimetable.repository",
})

Then the application loads but the controller will throw a 404 when trying to hit: http://localhost:8080/student/getAll然后应用程序加载,但 controller 在尝试命中时会抛出 404: http://localhost:8080/student/getAll

EDIT!!!编辑!!!

There was a few things wrong with the application at this point.此时应用程序出现了一些问题。 Firstly, the POM file needed updating首先,POM 文件需要更新

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>school-timetable</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>school-timetable</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-configuration</groupId>
            <artifactId>commons-configuration</artifactId>
            <version>1.9</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Secondly, the MAIN CLASS其次,MAIN CLASS

package com.example.schooltimetable;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@PropertySource("classpath:application.properties")
@EntityScan("com.example.schooltimetable.models.entities")
@EnableJpaRepositories("com.example.schooltimetable.repository")
public class SchoolTimetableApplication {
    public static void main(String[] args) {
        SpringApplication.run(SchoolTimetableApplication.class, args);
    }
}

There were also things wrong with the entities when joining columns: They should be set to read and write: false加入列时实体也有问题:它们应该设置为读写:false

package com.example.schooltimetable.models.entities;

import com.example.schooltimetable.models.constants.StudentEntityConstants;
import com.example.schooltimetable.models.constants.TimetableEntityConstants;
import org.springframework.lang.NonNull;

import javax.persistence.*;
import java.util.UUID;

@Entity
@Table(name = StudentEntityConstants.TABLE_NAME)
public class StudentEntity {

    @Id
    @Column(name = StudentEntityConstants.ID)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = StudentEntityConstants.FIRST_NAME)
    @NonNull
    private String firstName;

    @Column(name = StudentEntityConstants.LAST_NAME)
    @NonNull
    private String lastName;

    @Column(name = StudentEntityConstants.REFERENCE)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private UUID reference;

    @OneToOne(targetEntity = TimeTableEntity.class)
    @JoinColumn(name = TimetableEntityConstants.REFERENCE, updatable = false, insertable = false)
    private TimeTableEntity timeTable;

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public UUID getReference() {
        return this.reference;
    }

    public void setReference(UUID reference) {
        this.reference = reference;
    }

    public TimeTableEntity getTimeTable() {
        return this.timeTable;
    }
}

Thanks to @Abhinaba Chakraborty for pointing me in the right direction感谢@Abhinaba Chakraborty 为我指明了正确的方向

First of all, you don't need a component scan with the annotation SpringBootApplication in place.首先,您不需要使用注释SpringBootApplication进行组件扫描。 Spring automatically scans all components annotated with Component,Service,RestController,Respository,Configuration etc. and creates the Beans. Spring 自动扫描所有使用 Component、Service、RestController、Respository、Configuration 等注释的组件并创建 Bean。

The request mapping annotation value in StudentController should be prefixed with "/" eg. StudentController 中的请求映射注释值应以“/”为前缀,例如。 @RequestMapping("/student") - Although it has nothing to do with dependency injection. @RequestMapping("/student") - 虽然它与依赖注入无关。 But this is the reason why you are getting a 404 at http://localhost:8080/student/getAll但这就是您在 http://localhost:8080/student/getAll 获得 404 的原因

In the repository interface, just use @Repository annotation instead of having both @Repository and @Component annotations.在存储库接口中,只需使用@Repository 注解,而不是同时使用@Repository 和@Component 注解。

Also I dont see a data-jpa dependency defined in your POM.xml yet How are you importing the org.springframework.data.repository.CrudRepository in your repository.此外,我还没有看到在您的 POM.xml 中定义的 data-jpa 依赖项,您如何在存储库中导入org.springframework.data.repository.CrudRepository You need that dependency.你需要那种依赖。

As far as directory structure concerned, it looks OK,but please verify:就目录结构而言,它看起来不错,但请验证:

FIXED!!!固定的!!!

So the problem was with the way I'd implemented the @OneToOne relationship between the student and the Timetable.所以问题在于我在学生和时间表之间实现@OneToOne关系的方式。

The edit in the question was a work around as stated by @M.Deinum.正如@M.Deinum 所述,问题中的编辑是一种解决方法。 The correct solution was to first clean up the relationship between Student and Timetable, like so:正确的解决方案是首先清理 Student 和 Timetable 之间的关系,如下所示:

StudentEntity

package com.example.schooltimetable.models.entities;

import com.example.schooltimetable.models.constants.StudentEntityConstants;
import org.springframework.lang.NonNull;

import javax.persistence.*;

@Entity
@Table(name = StudentEntityConstants.TABLE_NAME)
public class StudentEntity {

    @Id
    @Column(name = StudentEntityConstants.ID)
    private long id;

    @Column(name = StudentEntityConstants.FIRST_NAME)
    @NonNull
    private String firstName;

    @Column(name = StudentEntityConstants.LAST_NAME)
    @NonNull
    private String lastName;

    @OneToOne(mappedBy = "student", cascade = CascadeType.ALL) // no need to join the columns on the Student. 
    private TimeTableEntity timeTable;

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public TimeTableEntity getTimeTable() {
        return this.timeTable;
    }

    public void setTimeTable(TimeTableEntity timeTable) { this.timeTable = timeTable; }
}

TimeTableEntity

package com.example.schooltimetable.models.entities;

import com.example.schooltimetable.models.constants.TimetableEntityConstants;

import javax.persistence.*;
import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.Set;

@Entity
@Table(name = TimetableEntityConstants.TABLE_NAME)
public class TimeTableEntity implements Serializable {

    @Id
    @Column(name = TimetableEntityConstants.ID)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @OneToOne
    @MapsId // <-- This automatically knows to join by the student ID column
    private StudentEntity student;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private final Set<ModuleEntity> modules = new LinkedHashSet();

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public void setStudent(StudentEntity student) {
        this.student = student;
    }

    public Set<ModuleEntity> getModules() {
        return this.modules;
    }

    public void setModules(ModuleEntity module) {
        this.modules.add(module);
    }
}

Now, the next few refactors, I could just do, I don't know why it worked all of a sudden but I have a feeling it was to do with the bad entity setup.I was able to remove the @EntityScan("com.example.schooltimetable.models.entities") & @EnableJpaRepositories("com.example.schooltimetable.repository")现在,接下来的几个重构,我可以做,我不知道为什么它会突然起作用,但我感觉这与错误的实体设置有关。我能够删除@EntityScan("com.example.schooltimetable.models.entities") & @EnableJpaRepositories("com.example.schooltimetable.repository")

Annotations from my main class, and I was also able to remove a lot of @Scope and @Component annotations from my code.我的主要 class 中的注释,我还能够从我的代码中删除很多@Scope@Component注释。 My main class now looks like this:我的主要 class 现在看起来像这样:

SchoolTimetableApplication

package com.example.schooltimetable;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;

@SpringBootApplication
@PropertySource("classpath:application.properties")
public class SchoolTimetableApplication {
    public static void main(String[] args) {
        SpringApplication.run(SchoolTimetableApplication.class, args);
    }
}

Much better!好多了! I also have data pulling through for the relationships rather than null (another issue I was facing).我也有数据通过关系而不是null (我面临的另一个问题)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 考虑在您的配置中定义一个“服务”类型的 bean [Spring boot] - Consider defining a bean of type 'service' in your configuration [Spring boot] 考虑在您的配置中定义一个类型为“Mapper”的 bean [Spring-Boot] - Consider defining a bean of type 'Mapper' in your configuration [Spring-Boot] 考虑在您的配置中定义一个类型为“package”的 bean [Spring-Boot] - Consider defining a bean of type 'package' in your configuration [Spring-Boot] 春季启动:考虑在配置中定义类型为“ com.repository.services.interfacename”的bean - Spring boot: Consider defining a bean of type 'com.repository.services.interfacename' in your configuration 考虑在您的配置中定义类型为“com.repository.UserRepository”的 bean - Consider defining a bean of type 'com.repository.UserRepository' in your configuration 使用 Spring JpaRepository 时,请考虑在 spring 引导中的配置中定义一个类型的 bean - Consider defining a bean of type in your configuration in spring boot when using Spring JpaRepository Spring 引导/MVC:考虑在配置中定义类型为“pack.website.repositories.CustomerRepository”的 bean - Spring Boot/MVC: Consider defining a bean of type 'pack.website.repositories.CustomerRepository' in your configuration 考虑在你的配置中定义一个类型为 * 的 bean - Consider defining a bean of type * in your configuration 考虑在配置中定义“包”类型的bean - Consider defining a bean of type 'package' in your configuration 考虑在你的配置中定义一个 'form' 类型的 bean - Consider defining a bean of type 'form' in your configuration
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM