Spring Data JPA & CRUD - GET PUT POST DELETE
Using JpaRepository
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
}
Avoiding Service layer for simplicity
Get a list of all the users
@RestController
@RequestMapping("/jpa")
public class StudentController {
@Autowired
private StudentRepository studentRepository;
// Retrieve all users, bypassing service
@GetMapping(path = "/students")
public List<Student> retrieveAllUsers() {
return studentRepository.findAll();
}
}
Get a student based on id
With support of the use of Java 8 OPTIONAL, Null values can be easily avoided.
// Retrieve specific users
@GetMapping(path = "/student/{id}")//from get request parameter
public Student retrieveUserById(@PathVariable("id") @NotBlank Long id) {
Optional<Student> optional = studentRepository.findById(id);//To Accommodate Null return
if (!optional.isPresent()){
throw new StudentNotFoundException("id:" + id);
}
Student foundStudent = optional.get();
return foundStudent;
}
Another Approach
// Retrieve specific users
@GetMapping(path = "/student/{id}")
public Student retrieveUserById(@PathVariable("id") @NotBlank Long id) {
return studentRepository.findById(id)
.orElseThrow(() -> new StudentNotFoundException("id:" + id));
}
POST Rest Calls (Creating a new Entity)
Doing this in Controller Class is not recommended. Service Layer is avoided for simplicity.
@PostMapping("/student")
public ResponseEntity<Object> createStudent(@Valid @RequestBody Student student){
System.err.println("###################################### POST Begins ######################################");
Student savedStud = studentRepository.save(student);
System.err.println("###################################### POST Ends ######################################");
URI location = ServletUriComponentsBuilder
.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(savedStud.getId())
.toUri();
return (ResponseEntity<Object>) ResponseEntity.created(location).build();
}
In Postman, create a POST call /api/jpa/student with Request Body RAW and JSON as
{
"name": "Nitin",
"dob": "2019-12-08T01:19:11.760+0000"
}
PUT Request (modifying an existing Value)
Use of Java 8 Map.
In this approach, A PUT Request can also be used to Create a new entry in case the passed id DOES NOT Exist in the DB. Not recommended to save, if ID doesn’t exist as id would not be known for a new entry
@PutMapping("/student/{id}")
public Student modifyValue(@RequestBody Student newStudent, @PathVariable Long id){
return studentRepository.findById(id)
.map(student -> {
student.setName(newStudent.getName());
student.setDob(newStudent.getDob());
return studentRepository.save(student);
})
.orElseGet(() -> {//Not recommended to save, if doesn't exist as ID WILL not be known for a new entry
newStudent.setId(id);
return studentRepository.save(newStudent);
});
}
Generic Exception (With Controller Advice)
Similar format of exception for all the Classes.
@RestController
@ControllerAdvice
public class CustomizedResponseEntiryExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(Exception.class)
public final ResponseEntity<Object> handleAllException(Exception ex, WebRequest request){
ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
DELETE Rest Call
In Controller
//Delete a User
@DeleteMapping(path = "/user/{id}")
public User deleteUserById(@PathVariable int id) throws UserNotFoundException {
User user = userDAOService.deleteById(id);
//If user is not found
if(user == null){
throw new UserNotFoundException("User with id " + id +" is not found");
}
return user;
}
in DAOService
//Delete a user
public User deleteById(int id){
Iterator<User> itr = users.iterator();
User deletedUser=null;
//boolean idExists = false;
while(itr.hasNext()){
User currentUser = itr.next();
if(id == currentUser.getId()){
//idExists=true;
deletedUser = currentUser;
itr.remove();
}
}
return deletedUser;
}
Delete a user by passing its ID to a delete postman request- * */api/hardCodedData/user/1**
Validations
Use of @Valid in the Controller class forces a validation check. The validation is defined in the Entity class
in Controller
//Add a new User
@PostMapping("/users")
public ResponseEntity<Object> addNewUser(@Valid @RequestBody User user){
User Entity Class (Using Lombok)
@Data
public class User {
private Integer id;
@Size(min=2,message = "Names should be at least characters long")
private String name;
@Past(message = "DOB Cannot be in the Future")
private Date dob;
}
Exception for Failed Validations in the customized response entity exception handler
//Exception for Failed Validations
@Override
private ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request){
ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), "Validation Failed", ex.getBindingResult().toString());
return new ResponseEntity(exceptionResponse, HttpStatus.BAD_REQUEST);
}