![](/img/trans.png)
[英]Consider defining a bean of type 'service' in your configuration [Spring boot]
[英]Spring Boot - Injecting Repository into Controller throws Consider defining a bean of type 'Type' in your configuration
我有一个 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();
}
}
我面临的问题是,每当我启动我的应用程序时,它都会引发以下错误:
***************************
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
我在尝试在另一个 class 中查找实体之前遇到了这个问题,我通过使用Application.java
中的@ComponentScan()
注释解决了这个问题,但是,它无法解决这个问题。
我的主应用程序文件如下所示:
学校时间表申请
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);
}
}
我的存储库看起来像这样: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> { }
存储库中引用的 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;
}
}
还有我的 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>
是不是我做错了什么? 我对 Spring/Boot 很陌生。 这个问题的一个有趣的注释是,如果我删除
@ComponentScan({
"com.example.schooltimetable.controllers", <---- This
"org.springframework.stereotype",
"com.example.schooltimetable.repository",
})
然后应用程序加载,但 controller 在尝试命中时会抛出 404: http://localhost:8080/student/getAll
编辑!!!
此时应用程序出现了一些问题。 首先,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>
其次,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);
}
}
加入列时实体也有问题:它们应该设置为读写: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;
}
}
感谢@Abhinaba Chakraborty 为我指明了正确的方向
首先,您不需要使用注释SpringBootApplication进行组件扫描。 Spring 自动扫描所有使用 Component、Service、RestController、Respository、Configuration 等注释的组件并创建 Bean。
StudentController 中的请求映射注释值应以“/”为前缀,例如。 @RequestMapping("/student") - 虽然它与依赖注入无关。 但这就是您在 http://localhost:8080/student/getAll 获得 404 的原因
在存储库接口中,只需使用@Repository 注解,而不是同时使用@Repository 和@Component 注解。
此外,我还没有看到在您的 POM.xml 中定义的 data-jpa 依赖项,您如何在存储库中导入org.springframework.data.repository.CrudRepository 。 你需要那种依赖。
就目录结构而言,它看起来不错,但请验证:
固定的!!!
所以问题在于我在学生和时间表之间实现@OneToOne
关系的方式。
正如@M.Deinum 所述,问题中的编辑是一种解决方法。 正确的解决方案是首先清理 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);
}
}
现在,接下来的几个重构,我可以做,我不知道为什么它会突然起作用,但我感觉这与错误的实体设置有关。我能够删除@EntityScan("com.example.schooltimetable.models.entities") & @EnableJpaRepositories("com.example.schooltimetable.repository")
我的主要 class 中的注释,我还能够从我的代码中删除很多@Scope
和@Component
注释。 我的主要 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);
}
}
好多了! 我也有数据通过关系而不是null
(我面临的另一个问题)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.