Close

Spring Data JPA - Derived Query Methods

[Last Updated: Aug 14, 2018]

Spring Data uses 'Query Methods' to map store-specific (JPA in this example) queries. Query methods are defined in the repository interface (by extending Repository or it's sub-interfaces including CrudRepository). Spring Data can derive queries directly from method name and parameters, or by explicit declared queries. In this example, we will see how to use method names to map JPA queries.

Example

We are going to extend CrudRepository and define our query methods. CrudRepository defines it's own query method which we saw in the last example.

JPA Entity

@Entity
public class Employee {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  private String dept;
  private int salary;
    .............
}

Defining Query Methods

public interface EmployeeRepository extends CrudRepository<Employee, Long> {
  List<Employee> findByDept(String deptName);
  List<Employee> findBySalaryGreaterThan(int salary);
  List<Employee> findByDeptAndSalaryLessThan(String deptName, int salary);
}

That's it. Now our query methods are ready to be used. We don't have to implement anything. During runtime, Spring Data will generate the JPA queries automatically by matching the target entity properties (employee#dept and employee#salary) and the special keywords (findBy, GreaterThan, And, LessThan etc).

Check out what keywords inside the query method names are supported here.

Example Client

@Component
public class ExampleClient {

  @Autowired
  private EmployeeRepository repo;

  public void run() {
      List<Employee> employees = createEmployees();

      System.out.println(" -- saving employees --");
      System.out.println(employees);
      repo.saveAll(employees);

      System.out.println(" -- finding all employees --");
      Iterable<Employee> all = repo.findAll();
      System.out.println(all);

      System.out.println(" -- finding by dept --");
      List<Employee> list = repo.findByDept("IT");
      list.stream().forEach(System.out::println);

      System.out.println(" -- finding by salary greater than 3000 --");
      List<Employee> list2 = repo.findBySalaryGreaterThan(3000);
      list2.stream().forEach(System.out::println);

      System.out.println(" -- finding by dept=IT and salary less than 4000 --");
      List<Employee> list3 = repo.findByDeptAndSalaryLessThan("IT", 4000);
      list3.stream().forEach(System.out::println);
  }

  private List<Employee> createEmployees() {
      return Arrays.asList(
              Employee.create("Diana", "Admin", 5000),
              Employee.create("Joe", "IT", 2000),
              Employee.create("Sophia", "IT", 6000),
              Employee.create("Mike", "Sale", 4000),
              Employee.create("Rose", "IT", 3000)
      );
  }
}

Main class

public class ExampleMain {

  public static void main(String[] args) {
      AnnotationConfigApplicationContext context =
              new AnnotationConfigApplicationContext(AppConfig.class);
      ExampleClient exampleClient = context.getBean(ExampleClient.class);
      exampleClient.run();
      EntityManagerFactory emf = context.getBean(EntityManagerFactory.class);
      emf.close();
  }
}
 -- saving employees --
[Employee{id=null, name='Diana', dept='Admin', salary=5000}, Employee{id=null, name='Joe', dept='IT', salary=2000}, Employee{id=null, name='Sophia', dept='IT', salary=6000}, Employee{id=null, name='Mike', dept='Sale', salary=4000}, Employee{id=null, name='Rose', dept='IT', salary=3000}]
-- finding all employees --
[Employee{id=1, name='Diana', dept='Admin', salary=5000}, Employee{id=2, name='Joe', dept='IT', salary=2000}, Employee{id=3, name='Sophia', dept='IT', salary=6000}, Employee{id=4, name='Mike', dept='Sale', salary=4000}, Employee{id=5, name='Rose', dept='IT', salary=3000}]
-- finding by dept --
Employee{id=2, name='Joe', dept='IT', salary=2000}
Employee{id=3, name='Sophia', dept='IT', salary=6000}
Employee{id=5, name='Rose', dept='IT', salary=3000}
-- finding by salary greater than 3000 --
Employee{id=1, name='Diana', dept='Admin', salary=5000}
Employee{id=3, name='Sophia', dept='IT', salary=6000}
Employee{id=4, name='Mike', dept='Sale', salary=4000}
-- finding by dept=IT and salary less than 4000 --
Employee{id=2, name='Joe', dept='IT', salary=2000}
Employee{id=5, name='Rose', dept='IT', salary=3000}

Note:

Check out the details about the algorithm which generates the queries here

Example Project

Dependencies and Technologies Used:

  • spring-data-jpa 2.0.6.RELEASE: Spring Data module for JPA repositories.
    Uses org.springframework:spring-context version 5.0.5.RELEASE
  • hibernate-core 5.2.13.Final: The core O/RM functionality as provided by Hibernate.
    Implements javax.persistence:javax.persistence-api version 2.1
  • h2 1.4.196: H2 Database Engine.
  • JDK 1.8
  • Maven 3.3.9

Spring Data JPA - Query Methods Select All Download
  • spring-data-jpa-query-method-basic
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • EmployeeRepository.java
          • resources
            • META-INF

    See Also