我尝试按照以下说明创建custom repository
https://www.baeldung.com/spring-data-jpa-method-in-all-repositories
我的应用构建失败,错误为NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.dao.ExtendedStudentRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
我的完整源代码
https://github.com/sesong11/springjpa-custom-repo
有很多类似的问题,但是没有一个适合我。也许是当前版本2.1.1的Spring问题,或者我错过了一些配置。
答案 0 :(得分:3)
要使测试正常进行,您必须执行以下操作:
1)将basePackages
中StudentJPAH2Config
的错误定义替换为com.example.demo.dao
,或者最好将其删除为多余的内容:
@Configuration
@EnableJpaRepositories(repositoryBaseClass = ExtendedRepositoryImpl.class)
public class StudentJPAH2Config {
}
2)还将basePackages
中的@ComponentScan
和@EntityScan
类中的DemoApplication
替换为com.example.demo.dao
和com.example.demo.entity
。或者最好完全删除这些和@EnableTransactionManagement
注释:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3)将no-argument constructor添加到实体Student
。
4)更正您的测试类-使用@DataJpaTest测试DAO层并导入StudentJPAH2Config
配置:
@RunWith(SpringRunner.class)
@DataJpaTest
@Import(StudentJPAH2Config.class)
public class ExtendedStudentRepositoryIntegrationTest {
//...
}
通过这些更正,我已经成功运行了您的测试。
答案 1 :(得分:1)
在运行测试之前,让我们确保主应用程序正在运行。实际上,它存在一些问题。
IllegalArgumentException
:不是托管类型:类com.example.demo.entity.Student
。问题是 @EntityScan("com.example.demo.entity.*")
。程序包名称不正确,因此不会扫描Student
类。
解决方案是@EntityScan("com.example.demo.entity")
。
PropertyReferenceException
:找不到类型attributeContainsText
的属性Student
!问题在于未设置存储库基类,JpaQueryLookupStrategy
认为应从方法名称RepositoryQuery
构造一个findByAttributeContainsText
。它识别出模式findBy{EntityPropertyName}
,但在attributeContainsText
中找不到字段Student
。
未设置存储库基类,因为未应用配置StudentJPAH2Config
。如果无法扫描配置,则不会应用该配置。
@ComponentScan("com.example.demo.dao")
不会扫描StudentJPAH2Config
所在的软件包。
解决方案是@ComponentScan("com.example.demo")
,它将同时扫描"com.example.demo"
和"com.example.demo.dao"
软件包 1 。
现在,当应用程序正常时,让我们回到测试中。
NoSuchBeanDefinitionException
:没有可用的com.example.demo.dao.ExtendedStudentRepository
类型的合格bean。问题在于 StudentJPAH2Config
不能构成整个配置,并且缺少一些bean。
解决方案是列出所有配置类。
@ContextConfiguration(classes = { StudentJPAH2Config.class, DemoApplication.class })
或
@ContextConfiguration(classes = DemoApplication.class)
或
@SpringBootTest
JpaSystemException
:没有实体com.example.demo.entity.Student
的默认构造函数。问题在于,休眠 2 需要Student
的默认构造函数:
@Entity
public class Student {
@Id
private long id;
private String name;
public Student() {}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
// getters & setters
}
1 @ComponentScan("com.example.demo.dao")
是多余的,因为其中的@SpringBootApplication
将被扫描此软件包。
2 休眠是Spring应用程序中的默认JPA提供程序。
答案 2 :(得分:0)
进行了以下更改:
@SpringBootApplication
@ComponentScan("com.example.demo.dao")
@EntityScan("com.example.demo.entity")
@EnableJpaRepositories(basePackages = "com.example.demo.dao",
repositoryBaseClass = ExtendedRepositoryImpl.class)
@EnableTransactionManagement
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
和StudentJPAH2Config类
@Configuration
@ComponentScan("com.example.demo")
@EnableJpaRepositories(basePackages = "com.example.demo.dao",
repositoryBaseClass = ExtendedRepositoryImpl.class)
public class StudentJPAH2Config {
// additional JPA Configuration
}
缺少空构造函数的学生类:
@Entity
public class Student {
public Student() {
}
public Student(long id, String name) {
this.id = id;
this.name = name;
}
@Id
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
结果
和应用程序运行状态
答案 3 :(得分:0)
您的自定义Spring Data JPA存储库基类的实现确实起作用。 Spring Boot Application Context中只有几项需要解决。您确实已将Spring Boot Starter模块声明为依赖项,所以我提交了pull request,其中所做的更改将所有手动配置上下文的责任移交给了Spring Auto Configuration工厂提供程序。
这里有一些有关通过测试所需的更改的注释,以及每个测试的一些简短详细信息。注意,要在测试范围之外运行Spring Boot Application,您将需要向类路径添加适当的JDBC供应商依赖项,以及任何Spring应用程序属性以定义数据源属性。定义数据源属性后,Spring Auto Config应该使用合理的设置来照顾任何EntityManager和TransactionManager。参见Spring Boot features - Working with SQL Databases。
@SpringBootApplication
和@EnableJpaRepositories
除外)。应用程序pom配置为依赖Spring Boot Starter模块,这些模块已经通过spring.factories提供了Spring Auto Configuration类,同时还确保满足所有其他依赖性。@EnableJpaRepositories
不需要声明basePackages
,因为Auto Config模块将默认使用Spring Main Application类下的所有软件包。仍然需要声明附加的repositoryBaseClass
。@ComponentScan
已删除,因为“自动配置”模块将对Spring Main Application类之下的所有软件包执行ComponentScan,该软件包已经在项目的顶级软件包中。此外,这是声明basePackages
扫描不包含@Configuration
类StudentJPAH2Config
类的值。@EntityScan
已删除,因为“自动配置”模块将在Spring Main Application类下的所有软件包中执行扫描。@EnableTransactionManagement
已删除,因为“自动配置”模块将执行相同的操作。application.properties
,因为它们依赖于H2
,但是pom仅在测试范围的类路径中提供了该依赖。此外,属性文件中设置的所有配置属性通常在存在H2时由Spring Starters自动配置。Student
上为休眠添加了默认的构造函数。除非使用@PersistenceConstructor
或@Immutable
,否则Hibernate在管理实体时需要此构造函数。ExtendedStudentRepositoryIntegrationTest
中为单元测试应用程序上下文配置了DemoApplicationTests
中为Spring Boot集成测试定义的上下文配置相同。当直接将@ContextConfiguration
与StudentJPAH2Config
一起使用时,在Spring Boot Main Application类上定义的配置(即ComponentScan,EntityScan,TransactionManagement)没有应用到Spring Test Application Context。Spring Application Starters(通常)分为两种类型的依赖项。
autoconfigure
模块在其POM中声明了最小的依赖关系集,但是在编译过程中构建了许多依赖关系。自动配置模块还通过位于包Configuration
中的spring.factories
文件来通告META-INF
类和工厂。 Spring Boot在引导阶段将加载这些配置类。最后,配置类将有选择地声明Bean,并根据在上下文中声明的其他Bean以及在类路径上实际找到的依赖项来进行其他应用程序上下文更改/增强。这允许根据要导入的库和最少的属性集进行常规/合理的默认配置。starter
模块(通常)不提供太多/任何类。它们的目的是提供POM,这些POM声明特定Spring项目的良好开发基线所需的依赖关系。启动程序模块还依赖于适用的autoconfigure
模块,这些模块与这些依赖项配对,使您可以快速开始使用应用程序运行。在大多数情况下,使用Spring Starters时,主驱动程序不应弄清楚需要在Spring上下文中手动配置的内容,而应该弄清楚在基线不适合您的情况下应取消配置的内容。当像您一样在线上关注以下教程/示例时,请记住,可能会显示一些与配置有关的项目。有时可能需要这些配置说明,但通常它们是为了显示非启动Spring应用程序所需的配置细节或透明性。
答案 4 :(得分:-1)
您需要在实现的类中添加注释。 您必须添加@Component或@Service批注,以使Spring能够进行注入
@Component
public class ExtendedRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements ExtendedRepository<T, ID> {
答案 5 :(得分:-1)
我认为您忘了对ExtendedStudentRepository
bean进行注释
package com.example.demo.dao;
import com.example.demo.entity.Student;
@Repository
public interface ExtendedStudentRepository extends ExtendedRepository<Student, Long> {
}
答案 6 :(得分:-1)
您需要进行以下更改才能解决此问题。另外,由于我本地没有JDK 11,因此我使用JDK 8执行了此操作。另外,我为了扩展问题而执行了ExtendedStudentRepositoryIntegrationTest.java。
@Configuration @ComponentScan("com.example.demo") @EnableJpaRepositories(basePackages = "com.example.demo.dao", repositoryBaseClass = ExtendedRepositoryImpl.class) public class StudentJPAH2Config {
@SpringBootApplication @ComponentScan("com.example.demo.dao") @EntityScan("com.example.demo.entity") @EnableTransactionManagement public class DemoApplication {
更改#1的原因是测试配置中没有组件扫描,spring无法在正确的软件包中查找依赖项。 #2是必需的,因为Student.java直接位于com.example.demo.entity包中,而不是在其任何子包中。您也可以在测试配置文件StudentJPAH2Config中指定@EntityScan,尽管这不是必需的。
现在,这解决了您面临的紧迫问题,但是仍然可以通过一些其他非常直接的问题来欢迎您,并且您可以从这里着手解决。
答案 7 :(得分:-1)
您必须在@Primary
类上添加ExtendedRepositoryImpl
注释。应该可以。
Spring基本上不能限定依赖项。 @Primary
将确保无论您在何处注入对ExtendedRepository
接口的依赖项,第一个合格bean(类)将是ExtendedRepositoryImpl
。
答案 8 :(得分:-1)
您必须删除@ContextConfiguration(classes = { StudentJPAH2Config.class })
并在测试类@SpringBootTest
上添加ExtendedStudentRepositoryIntegrationTest
注释,这将解决您目前遇到的错误NoSuchBeanDefinitionException
。
但是我又遇到了类似的错误:
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.example.demo.entity.Student
这是因为Spring无法扫描实体Student
。
为此,您必须将@EntityScan("com.example.demo.entity.*")
类的@EntityScan("com.example.demo.entity")
更改为DemoApplication
。
再次出现错误:
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property attributeContainsText found for type Student!
这是因为方法findByAttributeContainsText()
不是有效的方法。