2

I'm trying to implement custom method in Spring Data repository using Spring Boot 1.5.9.RELEASE. I created the repository:

package com.example.springdatademo;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
interface MyEntityRepository extends JpaRepository<MyEntity, String>, CustomMyEntityRepository {

}

Provided the custom repository:

package com.example.springdatademo;

interface CustomMyEntityRepository {
    MyEntity myCustomFindQuery();
}

And the implementation:

package com.example.springdatademo;

import org.springframework.stereotype.Component;

    @Component
    class CustomMyEntityRepositoryImpl implements CustomMyEntityRepository {


        @Override
        public MyEntity myCustomFindQuery() {
            System.out.println("hello from custom query implementation");
            return null;
        }
    }

Plus, I provided an invocation:

package com.example.springdatademo;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@EntityScan
@EnableJpaRepositories
@SpringBootApplication
public class SpringDataDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringDataDemoApplication.class, args);
    }

    @Bean
    public CommandLineRunner run(MyEntityRepository repository) {
        return (args) -> {
            final MyEntity myEntity1 = repository.myCustomFindQuery();
            repository.save(new MyEntity(1, "fieldTwo"));
            for (MyEntity myEntity : repository.findAll()) {
                System.out.println(myEntity);
            }
        };
    }

}

pom.xml is just plain one generated from spring initializer:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
<!--        <version>2.1.9.RELEASE</version>-->
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-data-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-data-demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

When running the project on Spring Boot 1.5.9.RELEASE I'm getting a problem on container creation: Caused by: java.lang.IllegalArgumentException: Failed to create query method public abstract com.example.springdatademo.MyEntity com.example.springdatademo.CustomMyEntityRepository.myCustomFindQuery()! No property myCustomFindQuery found for type MyEntity!

Changing the Spring Boot version to 2.1.9.RELEASE works fine and gives me the expected result.

I can't find any tips in spring-data-jpa-1.11.9.RELEASE documentation

7
  • I guess the interface should be named MyEntityRepositoryCustom Commented Oct 10, 2019 at 10:02
  • according to the documentation it doesn't matter as long as there is an Impl postfix. This is just a quick reproducible examle Commented Oct 10, 2019 at 10:04
  • can put it on github Commented Oct 10, 2019 at 10:09
  • May be you are looking into new docs. You have to check docs pertaining to the spring data version you are using. But give my suggestion a try. Also make sure all the three files are in same package, repository, customrepository and impl Commented Oct 10, 2019 at 10:11
  • @pvpkiran renaming didn't help. Also, the link I've provided refers to the actual version of the documentation used in code. Commented Oct 10, 2019 at 10:22

2 Answers 2

3

I just checked out your code and was able to fix it. This is what I did

Rename MyEntityRepositoryCustomImpl to MyEntityRepositoryImpl and

As I told you in my comment, cutom repository should be named MyEntityRepositoryCustom(I guess you already did this)

Naming convention is the key here. Impl class should be named <BaseRepository>Impl. And not <CustomRepository>Impl

Sign up to request clarification or add additional context in comments.

2 Comments

ahhhh I see now - the implementation must have the name of the base repository, not the custom repository.
although it's weird that you can have only 1 extension class per repository
0

If you want your current code to run then you need a @NamedQuery if you want to run hql or if you want to run native query @NamedNativeQuery with a name MyEntity.myCustomFindQuery in your Entity class

@NamedQuery(name="MyEntity.myCustomFindQuery", 
query="SELECT 1 as a, 'a' as b from MyEntity")

or

  @NamedNativeQuery(name="MyEntity.myCustomFindQuery", 
    query="SELECT 1 as a, 'a' as b", resultSetMapping="mapmyCustomFindQuery")

@SqlResultSetMapping(name = "mapmyCustomFindQuery", classes = {
        @ConstructorResult(targetClass = MyEntity.class, columns = {
                @ColumnResult(name = "a"), @ColumnResult(name = "b")
                
        })
})

Alternatively you can keep both repositories separate (means MyEntityRepository shouldn't extend MyEntityRepositoryCustom

in that case, your Application class will look like below

@Autowired 
    MyEntityRepository repository;
    
    @Autowired
    MyEntityRepositoryCustom entityRepositoryCustom;
    
    

    public static void main(String[] args) {
        SpringApplication.run(SpringDataDemoApplication.class, args);
    }

    @Bean
    public CommandLineRunner run() {
        return (args) -> {
            final MyEntity myEntity1 = entityRepositoryCustom.myCustomFindQuery();
            repository.save(new MyEntity(1, "fieldTwo"));
            for (MyEntity myEntity : repository.findAll()) {
                System.out.println(myEntity);
            }
        };
    }

5 Comments

I don't want to use the @NamedQuery approach - I want to extend the Spring Data repository
then I would suggest keeping custom repository separate becuase @Repository interface MyEntityRepository extends JpaRepository<MyEntity, String>, MyEntityRepositoryCustom will try to resolve action on all methods defined
this is the suggested way of extending the Spring Data repositories, as described in the documentation
could you please add the url of documentation

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.