没有找到适用于...自定义Spring Data仓库的属性。

63

我正在尝试实现自定义的Spring repository。我有以下接口:

public interface FilterRepositoryCustom {
    List<User> filterBy(String role);
}
实施:
public class FilterRepositoryImpl implements FilterRepositoryCustom {
...
}

并且“主”代码库,扩展我的自定义代码库:

public interface UserRepository extends JpaRepository<User, String>, FilterRepositoryCustom {
...
}

我正在使用Spring Boot,并根据 文档

默认情况下,Spring Boot将启用JPA存储库支持并查找 @SpringBootApplication所在的包(及其子包)。

当我运行我的应用程序时,我遇到了这个错误:

org.springframework.data.mapping.PropertyReferenceException: No property filterBy found for type User!

9个回答

101

问题在于你创建了 FilterRepositoryImpl,但是你在 UserRepository 中使用它。你需要创建 UserRepositoryImpl 才能使其工作。

阅读此文档以获取更多详细信息

基本上

public interface UserRepositoryCustom {
    List<User> filterBy(String role);
}

public class UserRepositoryImpl implements UserRepositoryCustom {
...
}

public interface UserRepository extends JpaRepository<User, String>, UserRepositoryCustom {
...
}

Spring Data 2.x 更新
这篇答案是针对 Spring 1.x 写的。正如Matt Forsythe指出的,Spring Data 2.0 版本中命名规则有所更改。实现类名由 最终的存储库接口名称+Impl后缀 改为 自定义接口名称+Impl后缀

因此,在这种情况下,实现类的名称应为:UserRepositoryCustomImpl


12
虽然我同意这个方法(并且已经看过实际操作),但我很难将其行为与链接文档中的内容协调起来,链接文档明确在名为UserRepository的存储库上使用了CustomizedUserRepositoryImpl。然后,文档进一步说明(示例29)同时在UserRepository上使用HumanRepositoryImplContactRepositoryImpl。它们似乎表明重要的是片段实现名称与片段接口名称匹配,而不是基本存储库名称,但从我所见的情况来看,这显然并不是这种情况。我感到困惑... - matt forsythe
26
我进行了更深入的挖掘并回答了自己的问题:实现名称必须基于基本存储库名称的要求仅适用于旧版(1.x)的spring-data。在spring-data的2.x版本中,此要求发生了变化。在2.x中,impl名称必须遵循自定义接口名称。 - matt forsythe
1
还有关于xxxRepository和xxxRepositoryImpl的包的问题。如果xxxRepository在com.test包中,则xxxRepositoryImpl应该在com.test.impl中。 - Bala
1
Spring文档中也有同样的问题:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementationsCustomizedUserRepository、CustomizedUserRepositoryImpl和UserRepository之间存在问题,但是这个问题可以得到解决,因为CustomizedUserRepositoryImpl应该被命名为UserRepositoryImpl。感谢您提供的解决方案。 - Guram Savinov
@mattforsythe的第二条评论也应该成为被接受的答案的一部分。 - Sayantan
显示剩余6条评论

6

如果FilterRepositoryCustom的实现类没有在你的Spring配置中被识别出来,那么这个错误可能会以另一种方式出现:

@EnableJpaRepositories(basePackageClasses = {RepoPackageMarker.class, FilterRepositoryCustomImpl.class})

5

我遇到了同样的问题。请检查您的包结构是否如下

custom
   impl
      - FilterRepositoryCustomImpl.class
- FilterRepositoryCustom.class      

因为当我尝试使用自定义仓库时,它无法看到该实现。 (实现应在同一包或子包中,以便Spring能够看到它)

也许对某些人有所帮助 (ノ^∇^)


"实现应该在同一个包或子包中,以便Spring能够看到它" 非常有用。谢谢。 - rios0rios0

3
CustomRepository 中的 customMethod() 方法是否必须只能定义以下两种类型的参数:

1.实体类名称 - customMethod(User user)

2.实体类属性 - customMethod(String firstName),其中 firstName 是 User 实体类的属性。

我是否不能使用 customMethod(CustomCriteria criteria) 这样的方法,其中 criteria 类包含用于构建动态查询的各种属性。

例如:getStatusByCriteria(CustomCriteria criteria),其中 CustomCriteria 是一个简单的 pojo,使用 @Component 进行注释以便Spring识别它。

当我尝试这样做时,会出现以下错误:

org.springframework.data.mapping.PropertyReferenceException: No property criteria found for type UserRepository!


2

与片段接口对应的类名最重要的部分是Impl后缀。


我简直不敢相信,它居然有效。 - Erick Luz

1

我也遇到了这个错误。这是因为我将elasticSearch仓库配置为了package。

@EnableElasticsearchRepositories("some.package")

接下来,我将MyElasticSearchRepository从“some.package”包移动到另一个包中,但没有更改配置。


1

对我来说,关键在于:

  1. @EnableJpaRepositories(repositoryBaseClass = MyRepositoryImpl.class)
  2. 在接口上使用@NoRepositoryBean注解

请按照您的Spring版本遵循文档 https://docs.spring.io/spring-data/data-commons/docs/2.3.4.RELEASE/reference/html/#repositories

因此,我的结果是:

@NoRepositoryBean
public interface SliceRepository<T, ID> extends JpaRepository<T, ID> {..}

public class SliceRepositoryImpl<T, ID> extends SimpleJpaRepository<T, ID> implements SliceRepository<T, ID> {..}


@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactory",
        basePackages = {"com.some.servicename.repository"},
        repositoryBaseClass = SliceRepositoryImpl.class
)

0

我在我的一个项目中遇到了同样的问题。我通过在我的pom.xml文件中添加一行来解决这个问题。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <includes>
            <include>com/my/package/entities/*.java</include>
            <include>com/my/package/repositories/*.java</include>
            <include>com/my/package/repositories/impl/*.java</include> <!-- add this -->
        </includes>
    </configuration>
</plugin>

-5

旧方法:

Entity aThing = repository.findOne(1L);

新方式:
Optional<Entity> aThing = repository.findById(1L);

4
欢迎来到Stack Overflow。虽然这段代码可能回答了问题,但提供有关为什么和/或如何回答问题的附加上下文可以提高其长期价值。如何回答问题 - Elletlar

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