ChatGPT解决这个技术问题 Extra ChatGPT

找不到类型的属性...自定义 Spring 数据存储库

I'm trying to implement a custom Spring repository. I have the interface:

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

the implementation:

public class FilterRepositoryImpl implements FilterRepositoryCustom {
...
}

and the "main" repository, extending my custom repository:

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

I'm using Spring Boot and, according to the docs:

By default, Spring Boot will enable JPA repository support and look in the package (and its subpackages) where @SpringBootApplication is located.

When I run my application, I get this error:

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


J
Jacob van Lingen

The problem here is that you are creating FilterRepositoryImpl but you are using it in UserRepository. You need to create UserRepositoryImpl to make this work.

Read this doc for more detail

Basically

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 update
This answer was written for Spring 1.x. As Matt Forsythe pointed out, the naming expectations changed with Spring Data 2.0. The implementation changed from the-final-repository-interface-name-with-an-additional-Impl-suffix to the-custom-interface-name-with-an-additional-Impl-suffix.

So in this case, the name of the implementation would be: UserRepositoryCustomImpl.


While I agree that this works (and have seen it in action), I am having a hard time reconciling this behavior with the linked documentation, which explicitly uses a CustomizedUserRepositoryImpl on a repository named UserRepository. The docs then go further (example 29) to use HumanRepositoryImpl AND ContactRepositoryImpl together on UserRepository. They seem to indicate that the important thing is for the fragment implementation name to match the fragment interface name, rather than the base repository name, but that is clearly not the case from what I have seen. I am confused...
Did some more digging and answered my own question: the requirement that the implementation name be based on the base repository name is only true for older (1.x) versions of spring-data. In version 2.x of spring-data, this requirement changes. In 2.x, the impl name must follow the custom interface name.
You saved my time and made me happy! Thanks, naming with Spring Data really maters, event for tests.
And also packages for xxxRepository & xxxRepositoryImpl matters. if xxxRepository is in com.test package then xxxRepositoryImpl sholuld be in com.test.impl
Same issue in Spring's docs: docs.spring.io/spring-data/jpa/docs/current/reference/html/… CustomizedUserRepository, CustomizedUserRepositoryImpl and UserRepository, but it doesn't work, because CustomizedUserRepositoryImpl should be UserRepositoryImpl Thanks for solution.
u
user64141

Another way this error can happen if the impl class for FilterRepositoryCustom isn't picked up in your spring configuration:

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

S
Suraj Kumar

Is it a must that the customMethod() in the CustomRepository can only have parameters defined that are either

1.Entity class name - customMethod(User user),

2.Entity class attributes - customMethod(String firstName), here firstName is an attribute of User Entity class.

Can I not have something like customMethod(CustomCriteria criteria), the criteria class contain the various attributes that are used to construct a dynamic query.

e.g. getStatusByCriteria(CustomCriteria criteria), CustomCriteria is a simple pojo annotated with @Component so that spring identifies it.

When I tried this I get an error:

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


A
Andrew Mikolyk

I had the same problem. Please check if your packages structure looks like this

custom
   impl
      - FilterRepositoryCustomImpl.class
- FilterRepositoryCustom.class      

Because when I try to use my custom repo it doesn't see the implementation. (implementation should be in the same package or in sub-packages for Spring to see it)

Maybe it helps somebody (ノ^∇^)


"implementation should be in the same package or in sub-packages for Spring to see it" very useful. Thanks.
A
Alex Xela

for me the keys was

@EnableJpaRepositories(repositoryBaseClass = MyRepositoryImpl.class) @NoRepositoryBean annotation on interface

follow the docs for your spring ver https://docs.spring.io/spring-data/data-commons/docs/2.3.4.RELEASE/reference/html/#repositories

so as result i have:

@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
)

O
Oleksandr Bondarchuk

I also had this error. It occured because I had configured elasticSearch repository with package

@EnableElasticsearchRepositories("some.package")

Next I moved MyElasticSearchRepository from package 'some.package' to another, but didn't change configuration


B
Bruno 82

I had the same problem in a project of mine. I solved the problem by adding a line in my 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>

p
pureevill

The most important part of the class name that corresponds to the fragment interface is the Impl postfix.


u
user692942

Old way:

Entity aThing = repository.findOne(1L);

New way:

Optional<Entity> aThing = repository.findById(1L);

Welcome to Stack Overflow. While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.How to Answer