Spring无法定位JpaRepository。

9

使用JavaConfig时,我在定位@Spring Repository的bean时遇到了问题。

该存储库接口定义如下:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    User findByUsername(String username);

}

配置定义如下:

@Configuration
@ComponentScan("com.example")
@EnableAutoConfiguration
@EnableJpaRepositories("com.example")
public class SampleApplication extends SpringBootServletInitializer {
...

包的结构如下:

com.example
     configuration
           SampleApplication
     repository
           UserRepository

从日志文件中我看到仓库(Repository)被认为是一个bean定义的候选对象,但是:

ClassPathBeanDefinitionScanner | Ignored because not a concrete top-level class:

有趣的事实

如果我将SampleApplication类移动到com.example包中,则一切都可以正常工作。

你有什么想法,我错过了什么吗?


1
虽然它几乎肯定与此无关,但您不需要在“UserRepository”上使用“@Repository”注释。Spring Data会创建扩展CrudRepository并位于您在配置中指定的包内的存储库。 - geoand
没问题!我希望我对这个问题有更多的见解。也许你应该添加Spring Boot标签。这样可以吸引更多人关注这个问题。 - geoand
我知道,但是有很多人会关注这些问题 :) - geoand
@geoand 如果谈到Spring Boot,如果你遵循“自动配置”的路径,一切似乎都很好,但是一旦你开始深入了解,你会突然意识到,整个应用程序正在崩溃,只因为你移动/重命名了一个单独的包。 - WeMakeSoftware
是的,这看起来非常奇怪!我希望开发Spring Boot的好人们会检查一下并提供他们的见解! - geoand
显示剩余3条评论
4个回答

16
如果你的JPA实体不在com.example.configuration子包中,则可能需要使用Spring Boot的@EntityScan注释。我建议您将@Configuration移出SpringBootServletInitializer并放入自己的类中。
如果您可以将配置类上移一级,则可以完全删除@ComponentScan@EnableJpaRepositories@EntityScan注释(请参阅http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-locating-the-main-class)。
如果@EntityScan不能解决问题,或许您可以提供一个我们可以查看的示例项目?

谢谢帮忙,@EntityScan("com.example") 完成了任务。 - WeMakeSoftware
我有一个多项目设置,其中实体位于一个单独的项目中,而存储库位于其他项目中,“@EntityScan”是唯一有用的技巧,谢谢。 - norbertas.gaulia

4
问题在于使用 @EnableJpaRepositories("com.example") 时,您的上下文在启动时会检查 com.example 作为基本包,但它不会继续向下扫描。换句话说,包扫描将停留在 com.example 级别。要进行更深入的扫描,您需要像这样做 @EnableJpaRepositories("com.example.**")。但是,在这种情况下,Spring Data 将检查所有包含 com.example 的包和所有子包。更正确的方法应该是编写类似于 @EnableJpaRepositories("com.example.repository")@EnableJpaRepositories("com.example.repository.**") 的语句。在第一种情况下,您扫描存储库基础包,在第二种情况下,您扫描存储库及其所有子包,我认为这是这种情况下的正确方法。
希望这可以帮助您。

0

我通常认为在@EnableJpaRepositories中指定的包会遍历内部包。

如果有疑问,您可以尝试类型安全的替代方法:

@Configuration
@ComponentScan("com.example")
@EnableAutoConfiguration
@EnableJpaRepositories (basePackageClasses = {UserRepository.class})
public class SampleApplication extends SpringBootServletInitializer {
...

尝试过了,但没有成功。问题在于它将UserRepository作为bean候选项找到,但后来被拒绝了。此外,如果我将SampleApplication类放在com.example包中,一切都可以顺利进行。 - WeMakeSoftware
一个问题:为什么你要使用SpringBootServletInitializer作为主类? - Gabriel Ruiu
我正在部署到Tomcat,但我需要一个选项来在独立模式下运行应用程序进行测试。 - WeMakeSoftware

0
 @EnableJpaRepositories (basePackageClasses = {SchedulerRepository.class})

在我的情况下对我有用,尽管我已经添加了所有的注释来选择存储库


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接