In this tutorial, we will learn how to configure Hibernate DAO layer in the spring boot application.
In this tutorial, we build a CRUD spring boot REST APIs with Hibernate as DAO layer and MySQL as database.
We are going to use three-layer architecture in our Spring boot project:
1. Create Spring Boot Project
Spring Boot provides a web tool called Spring Initializer to bootstrap an application quickly. Just go to https://start.spring.io/ and generate a new spring boot project.
2. Maven Dependencies
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.sourcecodeexamples.springboot</groupId> <artifactId>cruddemo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>cruddemo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
3. Configure MySQL Database
Spring Boot tries to auto-configure a DataSource if spring-data-jpa dependency is in the classpath by reading the database configuration from the application.properties file.
So, we just have to add the configuration, and Spring Boot will take care of the rest.
Open the application.properties file and add the following properties to it.
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username = root
spring.datasource.password = root
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
You will need to create a database named demo in MySQL, and change the spring.datasource.username & spring.datasource.password properties as per your MySQL installation.
In the above properties file, the last two properties are for Hibernate. Spring Boot uses Hibernate as the default JPA implementation.
The property spring.jpa.hibernate.ddl-auto is used for database initialization. I’ve used the value “update” for this property.
4. Create JPA Entity
Let's create a new package called entity inside com.sourcecodeexamples.springboot and add a class named Employee.java with the following contents:
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 {
// define fields
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private int id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@Column(name="email")
private String email;
// define constructors
public Employee() {
}
public Employee(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
// define getter/setter
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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
// define tostring
@Override
public String toString() {
return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
}
}
5. Create Repository or DAO Layer
The next thing we’re gonna do is create a DAO layer to access an Employee’s data from the database.
EmployeeDao Interface
import java.util.List; import com.sourcecodeexamples.springboot.cruddemo.entity.Employee; public interface EmployeeDAO { public List
findAll(); public Employee findById(int theId); public void save(Employee theEmployee); public void deleteById(int theId); }
EmployeeDaoImpl Class
import java.util.List; import javax.persistence.EntityManager; import org.hibernate.Session; import org.hibernate.query.Query; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.sourcecodeexamples.springboot.cruddemo.entity.Employee; @Repository public class EmployeeDAOHibernateImpl implements EmployeeDAO { // define field for entitymanager private EntityManager entityManager; // set up constructor injection @Autowired public EmployeeDAOHibernateImpl(EntityManager theEntityManager) { entityManager = theEntityManager; } @Override public List<Employee>
findAll() { // get the current hibernate session Session currentSession = entityManager.unwrap(Session.class); // create a query Query theQuery = currentSession.createQuery("from Employee", Employee.class); // execute query and get result list List employees = theQuery.getResultList(); // return the results return employees; } @Override public Employee findById(int theId) { // get the current hibernate session Session currentSession = entityManager.unwrap(Session.class); // get the employee Employee theEmployee = currentSession.get(Employee.class, theId); // return the employee return theEmployee; } @Override public void save(Employee theEmployee) { // get the current hibernate session Session currentSession = entityManager.unwrap(Session.class); // save employee currentSession.saveOrUpdate(theEmployee); } @Override public void deleteById(int theId) { // get the current hibernate session Session currentSession = entityManager.unwrap(Session.class); // delete object with primary key Query theQuery = currentSession.createQuery( "delete from Employee where id=:employeeId"); theQuery.setParameter("employeeId", theId); theQuery.executeUpdate(); } }
6. Create Service Layer
Service Interface
Let's create a package called service inside base package com.sourcecodeexamples.springboot. Create an EmployeeService interface with the following contents:
import java.util.List;
import com.sourcecodeexamples.springboot.cruddemo.entity.Employee;
public interface EmployeeService {
public List<Employee> findAll();
public Employee findById(int theId);
public void save(Employee theEmployee);
public void deleteById(int theId);
}
Service Interface Implementation
Let's create a package called impl inside package com.sourcecodeexamples.springboot.service. Create an EmployeeServiceImpl class with the following contents:
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sourcecodeexamples.springboot.cruddemo.dao.EmployeeDAO;
import com.sourcecodeexamples.springboot.cruddemo.entity.Employee;
@Service
public class EmployeeServiceImpl implements EmployeeService {
private EmployeeDAO employeeDAO;
@Autowired
public EmployeeServiceImpl(EmployeeDAO theEmployeeDAO) {
employeeDAO = theEmployeeDAO;
}
@Override
@Transactional
public List<Employee> findAll() {
return employeeDAO.findAll();
}
@Override
@Transactional
public Employee findById(int theId) {
return employeeDAO.findById(theId);
}
@Override
@Transactional
public void save(Employee theEmployee) {
employeeDAO.save(theEmployee);
}
@Override
@Transactional
public void deleteById(int theId) {
employeeDAO.deleteById(theId);
}
}
7. Create Controller Layer
We’ll now create the REST APIs for creating, retrieving, updating, and deleting an Employee.
First, create a new package controller inside base package com.sourcecodeexamples.springboot. Then, create a new class EmployeeController.java with the following contents -
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sourcecodeexamples.springboot.cruddemo.entity.Employee;
import com.sourcecodeexamples.springboot.cruddemo.service.EmployeeService;
@RestController
@RequestMapping("/api")
public class EmployeeRestController {
private EmployeeService employeeService;
@Autowired
public EmployeeRestController(EmployeeService theEmployeeService) {
employeeService = theEmployeeService;
}
// expose "/employees" and return list of employees
@GetMapping("/employees")
public List<Employee> findAll() {
return employeeService.findAll();
}
// add mapping for GET /employees/{employeeId}
@GetMapping("/employees/{employeeId}")
public Employee getEmployee(@PathVariable int employeeId) {
Employee theEmployee = employeeService.findById(employeeId);
if (theEmployee == null) {
throw new RuntimeException("Employee id not found - " + employeeId);
}
return theEmployee;
}
// add mapping for POST /employees - add new employee
@PostMapping("/employees")
public Employee addEmployee(@RequestBody Employee theEmployee) {
// also just in case they pass an id in JSON ... set id to 0
// this is to force a save of new item ... instead of update
theEmployee.setId(0);
employeeService.save(theEmployee);
return theEmployee;
}
// add mapping for PUT /employees - update existing employee
@PutMapping("/employees")
public Employee updateEmployee(@RequestBody Employee theEmployee) {
employeeService.save(theEmployee);
return theEmployee;
}
// add mapping for DELETE /employees/{employeeId} - delete employee
@DeleteMapping("/employees/{employeeId}")
public String deleteEmployee(@PathVariable int employeeId) {
Employee tempEmployee = employeeService.findById(employeeId);
// throw exception if null
if (tempEmployee == null) {
throw new RuntimeException("Employee id not found - " + employeeId);
}
employeeService.deleteById(employeeId);
return "Deleted employee id - " + employeeId;
}
}
8. Run Spring Boot Application
We’ve successfully built all the APIs for our application. Let’s now run the app and test the APIs.
Just go to the root directory of the application and type the following command to run it -
$ mvn spring-boot:run
The application will start at Spring Boot’s default tomcat port 8080.