Spring Data JPA + RESTful Api + H2 Embedded Database

Yunus Bagriyanik
7 min readJul 27, 2019

Travel of the data from database towards API in Spring Boot based coding.

In the first part of this series we gonna handle how to pull data from database into the api. We’re going to perform GET operation. In the next article series, we’ll examine the POST, PUT and DELETE operations.

Used Classes & Layers in Encoding

  • Base Entity and Data Models that representing models the database
  • Data Access Object(Derived Query Methods in Spring Data JPA Repositories)
  • Data Transfer Object (DTO)
  • Service Layer(Business Logic Layer)
  • RESTful Web Service(JAX-RS)

Base Entity

Base Entity class is important in terms of document information about who uploaded or updated the data. And also gives date information of data. Classes expanding from BaseEntity gain the functionality to track the history of entity changes. In other words observes changes to data. It doesn’t have any separate table in the database and no need to create an identity for each class.

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@MappedSuperclass
public abstract class BaseEntity implements Serializable {

private static final long serialVersionUID = 1L;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at", updatable =false)
private Date createdAt;
@Column(name = "created_by",length = 50, updatable = false)
private String createdBy;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "updated_at", insertable = false)
private Date updatedAt;
@Column(name = "updated_by",length = 50, insertable = false)
private String updatedBy;
// + Getters and setters
import org.hibernate.envers.Audited;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.util.Date;
@MappedSuperclass
@Auditedpublic
public abstract class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L; @CreatedDate
private Date createdAt;
@CreatedBy
private String createdBy;
@LastModifiedDate
private Date updatedAt;
@LastModifiedBy
private String updeatedBy;
+ Getters and setters

Both code examples above are correct when using the class of Base Entity structure.

Spring Data JPA provides some convenient and useful annotations for database auditing.

@Autidted, @CreatedDate, @CreatedBy, @LastModifiedDate, @LastModifiedBy

public abstract class BaseEntity — Making this class abstract prevents starting an instance of this class. Only classes that extend BaseEntity can start an instance.

@MappedSuperclass : When used @MappedSuperClass annotation BaseEntity class won’t have a separate representation as a table in the database. Briefly @MappedSuperclass indicates that the class is a baseentity.

@Autidted : This annotation used to automatically track changes in entity at a separate control panel.

updatable = false ; Related field property not included in the update queries generated by HQL.

insertable = false ; Related field property not included in the insert queries generated by HQL. Both are true by default.(updatable, insertable)

Data Models

Model: The layer responsible for the application data. We can say that is object definitions required for our application.

Entity: Entity can be defined as persistent objects that allow us to relate our database and application.

import javax.persistence.*;
import java.util.Objects;
//Data model
@Entity
@Table(name = "entity")
public class Entity extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Basic
@Column(name = "entity_name")
private String entname;
@Basic
@Column(name = "entity_code")
private String entcode;

public Entity (){

}

public Entity(Long id, String entname, String entcode) {
this.id = id;
this.entname = entname;
this.entcode = entcode;
}
+ Getters and setters@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
Entity entity = (Entity) o;
return Objects.equals(id, entity.id) &&
Objects.equals(entname, entity.entname) &&
Objects.equals(entcode, entity.entcode);
}
@Override
public int hashCode() {
return Objects.hash(id, entname, entcode);
}
}

@Basic anotation has two features optional and fetch. The optional property is a boolean parameter that determines whether the corresponding field allows a null value. It’s true by default. The Fetch attribute accepts a member of a Sorting List that specifies whether the marked field or feature wants to be lazily loaded or eager retrieved. It is set to FetchType.EAGER by default, but we can allow lazy loading by setting it to FetchType.LAZY.

Repository (Data Access Object)

Layers created in the software architecture must have little dependency on each other, and other layers should not be affected if a layer needs to be replaced. At this point it gives us many advantages. Depending on this, interdepartmental dependency is achieved through interface classes.

Data Access Object (DAO) design template usage; access to the preferred database and reduces the dependency of other layers to the database by further abstracting the data storage and data retrieval process. The classes that simplify JDBC technology used to transaction in the database are
located in DAO.

Spring Data JPA Repository

JPA

The Java Persistence API is a technology that allows relational data to be defined with Java classes and persists after the end of the application.

Spring Data JPA Repository

Spring Data is part of the Spring Framework. Spring Data JPA is part of Spring Data. The most important feature that Spring Data JPA Repository gives us is that it provides consistent basic functions. It simplifies the data access process for both relational and non-relational databases. Spring Data JPA ,significantly reduces the amount of code when implementing database access and processing functions.

JpaRepository allows us to obtain functionalities without writing methods. Spring Data uses Jpa and Hibernate in the background to process their generations, schema updates, and sql generation. It provides many Sql functionality only in the formatting of the method names. For example After adding findBy (), several criteria can be created with fields on Entity.

findByUsername(), findByEntityCode..

package com.yunus.bagriyanik.repository;

import com.yunus.bagriyanik.model.Entity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;


import java.util.List;

public interface Entity Repository extends JpaRepository<Entity, Long> {

Entity getByEntcode(String entcode);
List<Entity> getByEntcodeContains(String entcode);
Page<Entity> findAll(Pageable pageable);
List<Entity> findAll(Sort sort);
Entity getByEntcodeAndIdNot(String entcode, Long id);

}

Data Transfer Object (DTO)

The layer that we present data to the outside world. Since we do not want to open our own domain model to outside, we send the data to the service layer with some objects. So, the data we pull from the database comes to the service block as DTO class.

package com.yunus.bagriyanik.dto;

public class EntityDto {

private Long id;
private String entname;
private String entcode;

+ Getters and setters

}

Service Facade Design Pattern

Indicates that a class is a “Service” that is not an encapsulated state, defined as a process that is presented as a stand-alone interface in the model. In other words, the intermediate layer for the specific business logic (Business Logic Layer). Integrates data from multiple sources.

package com.yunus.bagriyanik.service;

import com.yunus.bagriyanik.dto.EntityDto;
import com.yunus.bagriyanik.model.Entity;
import com.yunus.bagriyanik.util.PaginationMod;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface EntityService {

EntityDto save(EntityDto entityDto);
EntityDto getById(Long id);
EntityDto getByEntcode(String entcode);
List<Entity> getByEntcodeContains(String entcode);
Boolean delete(Long id);
PaginationMod<EntityDto> getAllPageable(Pageable pageable);
EntityDto update(Long id, EntityDto entityDto);

}

Service Implementation (GET)

@Service
public class EntityServiceImpl implements EntityService {

private final EntityRepository entityRepository;
private final ModelMapper modelMapper;

@Autowired
public EntityServiceImpl(EntityRepository entityRepository, ModelMapper modelMapper) {
this.entityRepository = entityRepository;
this.modelMapper = modelMapper;
}
@Override
public EntityDto getById(Long id) {
Entity entity = entityRepository.getOne(id);
return modelMapper.map(entity, EntityDto.class);
}
@Override
public PaginationMod<EntityDto> getAllPageable(Pageable pageable) {
Page<Entity> pagesOfentity = entityRepository.findAll(pageable);
PaginationMod paginationMod = new PaginationMod<EntityDto>(); //response of Pagination request
EntityDto[] entityDtos = modelMapper.map(pagesOfentity.getContent(),EntityDto[].class);
paginationMod.setValue(pagesOfentity, Arrays.asList(entityDtos));
return paginationMod;
}

Firstly we injected repository and modelmapper to implementation service. We used getById method retrieved the entity from the database with the associated id. Then we converted the entity class to the dto class with the help of modelmapper.

package com.yunus.bagriyanik.util;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import java.util.List;

public class PaginationMod<T> {
// page module to talk with service that we create private int number;
private int size;
private Sort sort;
private int totalPages;
private Long totalElements;
private List<T> content; // data that returned
// calling the setvalue method creates an instance of the paginationModule object
// filled our own object through Spring's Page
public void setValue(Page page, List<T> list){
this.number = page.getNumber();
this.size = page.getSize();
this.sort = page.getSort();
this.totalPages = page.getTotalPages();
this.totalElements = page.getTotalElements();
this.content = list;
}
+Getters and setters

We are talking to the service with the Pagination Mod generic class object that we created under Util package. It’s expecting a type from us. We placed the types in the Page model into our class. In doing so, we returned the pagination responses with our own object.

RESTful Web Services

In future articles I will talk in detail about RESTful architecture. Therefore, I will briefly describe in this article.

RESTful api is a web service approach implemented with HTTP methods over HTTP protocol. With REST, HTTP reapplication level is used as protocol.

package com.yunus.bagriyanik.util;

public final class ApiPaths {

private static final String BASE_PATH="/api";

public static final class Entity {
public static final String BPA = BASE_PATH+"/entity";
}

}
@RestController
@RequestMapping(ApiPaths.Entity.BPA)
public class EntityController {

private final EntityServiceImpl entityService;

@Autowired
public EntityController(EntityServiceImpl entityService) {
this.entityService = entityService;
}
// @GetMapping("/{id}")
@RequestMapping(value ="/getEntity/{id}",method=RequestMethod.GET)
public ResponseEntity<EntityIDto>getById
(@PathVariable(value="id",required = true) Long id){
log.info("Initializing entityServiceImpl :"+EntityServiceImpl.class); EntityDto entityDto = entityService.getById(id);
return ResponseEntity.ok(entityDto);
}
//PaginationMod<T>: create response object for pagination
@GetMapping("/pagination")
public ResponseEntity<PaginationMod<EntityDto>> getAllPageable(Pageable pageable){
PaginationMod<EntityDto>pages=entityService.
getAllPageable(pageable);
return ResponseEntity.ok(pages);
}

Client [Request] (GET) →http://localhost:8080/api/entity/{id}

Server [Response 200 Ok] → Media type JSON

{
“id” : { id },
“entname”: ”Entity Test Name”,
“entcode”: ”9876518"
}

The data journey ended with api’s method. The point to note here is that we presented the data to the api with the dto object.

Click GitHub Source Codes

I hope this quick read helped us get some ideas for the GET api.

--

--