Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable query creation from method name - use of projections

I would like to use the Spring Data Projection technique in order to extract from a table only some fields (and not all fields of the table).

As described in the documentation (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections) I created a simple interface, for example:

interface NamesOnly {
  String getFirstname();
  String getLastname();
}

But I have some problems to use it.

Problem 1:

First of all, I would like to use the name findAll() to create a query that finds all rows with only two fields (firstName and lastName):

@Repository
public interface PersonaRepository extends JpaRepository<Persona, Long> {
    List<NamesOnly> findAll();
}

But in this case I have these errors (maybe because findAll() is a method of the JpaRepository):

  • implements org.springframework.data.jpa.repository.JpaRepository.findAll
  • The return type is incompatible with JpaRepository.findAll()

Problem 2:

Ok, so I try to change the name of the method to findAllOnlyNames():

@Repository
public interface PersonaRepository extends JpaRepository<Persona, Long> {
    List<NamesOnly> findAllOnlyNames();
}

But now I have this error:

Caused by: org.springframework.data.mapping.PropertyReferenceException: No property findAllOnlyNames found for type Persona!

Because Spring tries to create a query from the name.

1) Could it be possible to reuse the method name findAll() without having problems with JpaRepository?

2) Could it be possible to turn off the query creation from the method name (only for some queries, not for all projects or repositories)?

like image 337
Andrea Bevilacqua Avatar asked Sep 14 '17 15:09

Andrea Bevilacqua


2 Answers

You are on the right track, your findAll() is in conflict with the ones specified on the existing Spring Data interfaces and you can rename it (as you tried) but it still has to be a name that is compatible with the query derivation mechanism. Try this instead:

@Repository
public interface PersonaRepository extends JpaRepository<Persona, Long> {
    List<NamesOnly> findAllOnlyNamesBy();
}

This part of the Spring Data JPA documentation explains how the query creation process works:

The mechanism strips the prefixes find…By, read…By, query…By, count…By, and get…By from the method and starts parsing the rest of it.

So you just need to add the By keyword in the method name, anything after that keyword is treated as a condition, in this case there is no condition so it fetches everything.

To disable the query derivation from the method name you would need to add an @Query(...) annotation to the method and specify either a JPA or native query instead.

like image 141
Robert Hunt Avatar answered Oct 23 '22 15:10

Robert Hunt


You can specify an explicit query rather than rely on it being derived from the method name.

@Repository
public interface PersonaRepository extends JpaRepository<Persona, Long> {
    @Query("select p from Persona p")
    List<NamesOnly> findAllOnlyNames();
}

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query

Overriding findAll() (even in the unlikely event it is possible) is probably a bad idea.

like image 2
Alan Hay Avatar answered Oct 23 '22 15:10

Alan Hay