javaspring-bootjpaspring-boot-3jparepository

Derived query method not working in JPA if the property contains string "Matches" in it


Derived query method not working in JPA if the property contains string "Matches" in it.

For example consider an entity class -

@Entity
@Getter
@Setter
@NoArgsConstructor
public class Players {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int player_id;
    private String name;
    private String nationality;
    private String position;
    private int playedMatches;
}

service class -

@Service
public class PlayerService {

    @Autowired
    PlayerRepository playerRepository;
    
    public ResponseEntity<Object> getByMayches(int played_matches){
        Optional<Players> optionalPlayers = playerRepository.findByPlayedMatches(played_matches);
        return ResponseEntity.ok(optionalPlayers.get());
    }
}

Repository -

public interface PlayerRepository extends JpaRepository<Players,Integer>{
    Optional<Players> findByPlayedMatches(int played_matches);
}

If I run application with the above setup, I ended up getting below error-

2024-10-11T19:12:25.853+05:30 ERROR 14096 --- [cricketApplication] [  restartedMain] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'playerService': Unsatisfied dependency expressed through field 'playerRepository': Error creating bean with name 'playerRepository' defined in com.fresco.cricket.repo.PlayerRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract java.util.Optional com.fresco.cricket.repo.PlayerRepository.findByPlayedMatches(int); Reason: Failed to create query for method public abstract java.util.Optional com.fresco.cricket.repo.PlayerRepository.findByPlayedMatches(int); No property 'played' found for type 'Players'
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:788) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:768) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:509) ~[spring-beans-6.1.13.jar:6.1.13]      
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1439) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971) ~[spring-context-6.1.13.jar:6.1.13]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.13.jar:6.1.13]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.4.jar:3.3.4]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.4.jar:3.3.4]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.4.jar:3.3.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.4.jar:3.3.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.4.jar:3.3.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.4.jar:3.3.4]
        at com.fresco.cricket.CricketApplication.main(CricketApplication.java:10) ~[classes/:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
        at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.3.4.jar:3.3.4]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'playerRepository' defined in com.fresco.cricket.repo.PlayerRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract java.util.Optional com.fresco.cricket.repo.PlayerRepository.findByPlayedMatches(int); Reason: Failed to create query for method public abstract java.util.Optional com.fresco.cricket.repo.PlayerRepository.findByPlayedMatches(int); No property 'played' found for type 'Players'
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1806) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:785) ~[spring-beans-6.1.13.jar:6.1.13]
        ... 25 common frames omitted
Caused by: org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract java.util.Optional com.fresco.cricket.repo.PlayerRepository.findByPlayedMatches(int); Reason: Failed to create query for method public abstract java.util.Optional com.fresco.cricket.repo.PlayerRepository.findByPlayedMatches(int); No property 'played' found for type 'Players'       
        at org.springframework.data.repository.query.QueryCreationException.create(QueryCreationException.java:101) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:119) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.mapMethodsToQuery(QueryExecutorMethodInterceptor.java:103) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lambda$new$0(QueryExecutorMethodInterceptor.java:92) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at java.base/java.util.Optional.map(Unknown Source) ~[na:na]
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.<init>(QueryExecutorMethodInterceptor.java:92) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:357) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:286) ~[spring-data-commons-3.3.4.jar:3.3.4]       
        at org.springframework.data.util.Lazy.getNullable(Lazy.java:135) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.util.Lazy.get(Lazy.java:113) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:292) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:132) ~[spring-data-jpa-3.3.4.jar:3.3.4]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853) ~[spring-beans-6.1.13.jar:6.1.13]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802) ~[spring-beans-6.1.13.jar:6.1.13]
        ... 35 common frames omitted
Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.Optional com.fresco.cricket.repo.PlayerRepository.findByPlayedMatches(int); No property 'played' found for type 'Players'
        at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:107) ~[spring-data-jpa-3.3.4.jar:3.3.4]
        at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:124) ~[spring-data-jpa-3.3.4.jar:3.3.4]
        at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:258) ~[spring-data-jpa-3.3.4.jar:3.3.4]     
        at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:95) ~[spring-data-jpa-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:115) ~[spring-data-commons-3.3.4.jar:3.3.4]
        ... 47 common frames omitted
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property 'played' found for type 'Players'
        at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:94) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:455) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:431) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.mapping.PropertyPath.lambda$from$0(PropertyPath.java:384) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(Unknown Source) ~[na:na]
        at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:366) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:344) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.query.parser.Part.<init>(Part.java:81) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.query.parser.PartTree$OrPart.lambda$new$0(PartTree.java:259) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(Unknown Source) ~[na:na]
        at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Unknown Source) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source) ~[na:na]
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline.collect(Unknown Source) ~[na:na]
        at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:260) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.query.parser.PartTree$Predicate.lambda$new$0(PartTree.java:389) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(Unknown Source) ~[na:na]
        at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Unknown Source) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source) ~[na:na]
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source) ~[na:na]
        at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source) ~[na:na]
        at java.base/java.util.stream.ReferencePipeline.collect(Unknown Source) ~[na:na]
        at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:390) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:103) ~[spring-data-commons-3.3.4.jar:3.3.4]
        at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:101) ~[spring-data-jpa-3.3.4.jar:3.3.4]
        ... 51 common frames omitted

But if I am changing property name in my entity from playedMatches to playedGames, application is running successfully

@Entity
@Getter
@Setter
@NoArgsConstructor
public class Players {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int player_id;
    private String name;
    private String nationality;
    private String position;
    private int playedGames;
}

@Service
public class PlayerService {

    @Autowired
    PlayerRepository playerRepository;
    
    public ResponseEntity<Object> getByMayches(int played_matches){
        Optional<Players> optionalPlayers = playerRepository.findByplayedGames(played_matches);
        return ResponseEntity.ok(optionalPlayers.get());
    }
}


public interface PlayerRepository extends JpaRepository<Players, Integer> {
    Optional<Players> findByplayedGames(int playedMatches);
}

Application is running successfully with the above setup.

Whats wrong with the word matches in the first case?


Solution

  • Matches is a reserved keyword as detailed here:

    https://docs.spring.io/spring-data/jpa/reference/repositories/query-keywords-reference.html#appendix.query.method.subject

    Short of changing the property name then the only way I can see to deal with it is to add an explicit query:

    @Query("FROM Players p where p.playedMatches = ?1")
    Optional<Players> findByPlayedMatches(int played_matches);