Friday 13 December 2019

Spring Data Rest: Working with Query Methods


This is continuation to my previous post. You can download my previous application from this location.

In this post, you are going to learn how to trigger REST APIs for query methods.

Step 1: Update Employee class like below.

Employee.java
package com.sample.app.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "employee")
public class Employee {
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "employee_id")
 private int id;

 @Column(name = "first_name")
 private String firstName;

 @Column(name = "last_name")
 private String lastName;

 @Column(name = "age")
 private int age;

 @Column(name = "salary")
 private double salary;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public double getSalary() {
  return salary;
 }

 public void setSalary(double salary) {
  this.salary = salary;
 }

 public static EmployeeBuilder builder() {
  return new EmployeeBuilder();
 }

 public static class EmployeeBuilder {
  private Employee emp;

  public EmployeeBuilder() {
   emp = new Employee();
  }

  public EmployeeBuilder firstName(String firstName) {
   emp.setFirstName(firstName);
   return this;
  }

  public EmployeeBuilder lastName(String lastName) {
   emp.setLastName(lastName);
   return this;
  }

  public EmployeeBuilder age(int age) {
   emp.setAge(age);
   return this;
  }

  public EmployeeBuilder salary(double salary) {
   emp.setSalary(salary);
   return this;
  }

  public Employee build() {
   return emp;
  }
 }

 @Override
 public String toString() {
  StringBuilder builder = new StringBuilder();
  builder.append("Employee [id=").append(id).append(", firstName=").append(firstName).append(", lastName=")
    .append(lastName).append(", age=").append(age).append(", salary=").append(salary).append("]");
  return builder.toString();
 }

}


Step 2: Update EmployeeRepository by adding query methods.
package com.sample.app.repository;

import java.util.List;

import org.springframework.data.repository.CrudRepository;

import com.sample.app.model.Employee;

public interface EmployeeRepository extends CrudRepository<Employee, Integer> {

 // SELECT * FROM employee WHERE salary=X
 public List<Employee> findBySalary(double salary);

 // SELECT * FROM employee WHERE lastName=X
 public List<Employee> findByLastName(String lastName);

 // SELECT * FROM employee WHERE age>X
 public List<Employee> findByAgeGreaterThan(int age);

 // SELECT * FROM employee WHERE age=X AND salary=Y
 public List<Employee> findByAgeAndSalary(int age, double salary);

}


Step 3: Update App.java by inserting default data.
package com.sample.app;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import com.sample.app.model.Employee;
import com.sample.app.repository.EmployeeRepository;

@SpringBootApplication
public class App {
 public static void main(String[] args) {

  SpringApplication.run(App.class, args);
 }


 @Bean
 public CommandLineRunner demo(EmployeeRepository employeeRepository) {
  return (args) -> {
   Employee emp1 = Employee.builder().firstName("Ram").lastName("Gurram").age(32).salary(100000.23).build();
   Employee emp2 = Employee.builder().firstName("Joel").lastName("Chelli").age(43).salary(60000).build();
   Employee emp3 = Employee.builder().firstName("Gopi").lastName("Battu").age(45).salary(1000000).build();
   Employee emp4 = Employee.builder().firstName("Bomma").lastName("Srikanth").age(39).salary(60000).build();
   Employee emp5 = Employee.builder().firstName("Surendra").lastName("Sami").age(32).salary(100000.23).build();

   employeeRepository.save(emp1);
   employeeRepository.save(emp2);
   employeeRepository.save(emp3);
   employeeRepository.save(emp4);
   employeeRepository.save(emp5);

  };
 }
}


Run App.java, you can see below messages in console.
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.6.RELEASE)

Hibernate: 
    
    drop table employee if exists
Hibernate: 
    
    drop sequence if exists hibernate_sequence
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: 
    
    create table employee (
       employee_id integer not null,
        age integer,
        first_name varchar(255),
        last_name varchar(255),
        salary double,
        primary key (employee_id)
    )
2019-07-10 11:19:58.279  WARN 11859 --- [           main] aWebConfiguration$JpaWebMvcConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        employee
        (age, first_name, last_name, salary, employee_id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        employee
        (age, first_name, last_name, salary, employee_id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        employee
        (age, first_name, last_name, salary, employee_id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        employee
        (age, first_name, last_name, salary, employee_id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        employee
        (age, first_name, last_name, salary, employee_id) 
    values
        (?, ?, ?, ?, ?)
Richardson Maturity Scale

Get all employee details
Method: GET
API: http://localhost:8080/api/employees


Once you hit above request, you will get below response.
{
  "_embedded" : {
    "employees" : [ {
      "firstName" : "Ram",
      "lastName" : "Gurram",
      "age" : 32,
      "salary" : 100000.23,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/1"
        },
        "employee" : {
          "href" : "http://localhost:8080/api/employees/1"
        }
      }
    }, {
      "firstName" : "Joel",
      "lastName" : "Chelli",
      "age" : 43,
      "salary" : 60000.0,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/2"
        },
        "employee" : {
          "href" : "http://localhost:8080/api/employees/2"
        }
      }
    }, {
      "firstName" : "Gopi",
      "lastName" : "Battu",
      "age" : 45,
      "salary" : 1000000.0,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/3"
        },
        "employee" : {
          "href" : "http://localhost:8080/api/employees/3"
        }
      }
    }, {
      "firstName" : "Bomma",
      "lastName" : "Srikanth",
      "age" : 39,
      "salary" : 60000.0,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/4"
        },
        "employee" : {
          "href" : "http://localhost:8080/api/employees/4"
        }
      }
    }, {
      "firstName" : "Surendra",
      "lastName" : "Sami",
      "age" : 32,
      "salary" : 100000.23,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/5"
        },
        "employee" : {
          "href" : "http://localhost:8080/api/employees/5"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/api/employees"
    },
    "profile" : {
      "href" : "http://localhost:8080/api/profile/employees"
    },
    "search" : {
      "href" : "http://localhost:8080/api/employees/search"
    }
  }
}

As you see "links" section of response, there is a "http://localhost:8080/api/employees/search" api under "search" section. We should use "search" API to trigger query methods.

How to get the APIS for query methods?
Hit the uri 'http://localhost:8080/api/employees/search' to get metadata of query methods.


Response looks like below.
{
  "_links" : {
    "findByLastName" : {
      "href" : "http://localhost:8080/api/employees/search/findByLastName{?lastName}",
      "templated" : true
    },
    "findByAgeAndSalary" : {
      "href" : "http://localhost:8080/api/employees/search/findByAgeAndSalary{?age,salary}",
      "templated" : true
    },
    "findBySalary" : {
      "href" : "http://localhost:8080/api/employees/search/findBySalary{?salary}",
      "templated" : true
    },
    "findByAgeGreaterThan" : {
      "href" : "http://localhost:8080/api/employees/search/findByAgeGreaterThan{?age}",
      "templated" : true
    },
    "self" : {
      "href" : "http://localhost:8080/api/employees/search"
    }
  }
}

Find employee whose age > 40

http://localhost:8080/api/employees/search/findByAgeGreaterThan?age=40
{
  "_embedded" : {
    "employees" : [ {
      "firstName" : "Joel",
      "lastName" : "Chelli",
      "age" : 43,
      "salary" : 60000.0,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/2"
        },
        "employee" : {
          "href" : "http://localhost:8080/api/employees/2"
        }
      }
    }, {
      "firstName" : "Gopi",
      "lastName" : "Battu",
      "age" : 45,
      "salary" : 1000000.0,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/3"
        },
        "employee" : {
          "href" : "http://localhost:8080/api/employees/3"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/api/employees/search/findByAgeGreaterThan?age=40"
    }
  }
}

Find employees whose age is 32 and salary is 100000.23
http://localhost:8080/api/employees/search/findByAgeAndSalary?age=32&salary=100000.23
{
  "_embedded" : {
    "employees" : [ {
      "firstName" : "Ram",
      "lastName" : "Gurram",
      "age" : 32,
      "salary" : 100000.23,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/1"
        },
        "employee" : {
          "href" : "http://localhost:8080/api/employees/1"
        }
      }
    }, {
      "firstName" : "Surendra",
      "lastName" : "Sami",
      "age" : 32,
      "salary" : 100000.23,
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/5"
        },
        "employee" : {
          "href" : "http://localhost:8080/api/employees/5"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/api/employees/search/findByAgeAndSalary?age=32&salary=100000.23"
    }
  }
}

You can download complete working application from this link.


Previous                                                    Next                                                    Home

No comments:

Post a Comment