In this tutorial, we will create a Spring Boot application that uses a DAO (Data Access Object) pattern. We perform CRUD operations with the MySQL database using the DAO pattern in the Spring boot project.
We will use the latest Spring Boot 3, Spring Data JPA (Hibernate), and MySQL 8+ Database.
DAO (Data Access Object) Pattern Overview
The DAO (Data Access Object) pattern is a design pattern that separates the data access logic from the business logic in an application. It provides a structured way to interact with a data storage system, such as a database, while abstracting the underlying implementation details.
The main purpose of the DAO pattern is to create a dedicated layer that handles all the interactions with the data storage system. This layer encapsulates the low-level operations required to perform CRUD (Create, Read, Update, Delete) operations on data entities, hiding the complexity of the data access logic from the rest of the application.
By using the DAO pattern, you can achieve separation of concerns and improve modularity and maintainability in your application.
The DAO pattern typically consists of the following components:
- Entity: Represents the data model or domain object that is persisted in the data storage system.
- DAO Interface: Defines the contract or interface that specifies the operations to be performed on the entity.
- DAO Implementation: Provides the actual implementation of the DAO interface, handling the low-level data access operations.
- Service Layer: Acts as an intermediary between the DAO layer and the business logic components, coordinating the interactions between them.
Using DAO in Spring Boot Application
In Spring Boot, we can leverage Spring Data JPA, which provides a convenient way to implement the DAO pattern. Spring Data JPA automatically generates the implementation of the DAO interface based on conventions and provides a wide range of database operations out of the box, reducing the need for boilerplate code.
Overall, the DAO pattern in Spring Boot enables you to abstract away the complexities of data access and focus on writing business logic in a clean and maintainable manner.
1. Create and Set up Spring Boot Project
<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>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Next, let's create the necessary components for the DAO pattern
2. Configure MySQL Database
Here are the configuration properties used in a Spring Boot application to configure the database connection and Hibernate settings for a MySQL database.
spring.datasource.url=jdbc:mysql://localhost:3306/ems
spring.datasource.username=root
spring.datasource.password=Mysql@123
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto=update
- spring.datasource.url: Specifies the JDBC URL for the MySQL database.
- spring.datasource.username: Sets the username for the database connection.
- spring.datasource.password: Sets the password for the database connection.
- spring.jpa.properties.hibernate.dialect: Specifies the Hibernate dialect to use for MySQL. It is set to org.hibernate.dialect.MySQLDialect, which is the dialect for MySQL databases.
- spring.jpa.hibernate.ddl-auto: Determines how Hibernate handles the database schema creation and migration. In this case, it is set to update, which means Hibernate will automatically create or update the database schema based on the entity classes and the current schema state.
3. Department JPA Entity
Create a Department class representing the Department entity with an id, departmentName, and departmentDescription fields. Add appropriate getters and setters.
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "departments")
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "department_name")
private String departmentName;
@Column(name = "department_description")
private String departmentDescription;
}
4. DepartmentRepository
Create a DepartmentRepository interface that extends JpaRepository to perform CRUD operations on the Department entity.
import net.javaguides.ems.entity.Department;
import org.springframework.data.jpa.repository.JpaRepository;
public interface DepartmentRepository extends JpaRepository<Department, Long> {
}
Note that we are leveraging Spring Data JPA to implement the DAO pattern. Spring Data JPA automatically generates the implementation of the DAO interface based on conventions and provides a wide range of database operations out of the box, reducing the need for boilerplate code.
DAO pattern in Spring Boot enables you to abstract away the complexities of data access and focus on writing business logic in a clean and maintainable manner.
5. Create DTO, Mapper, and ResourceNotFoundException Classes
DepartmentDto
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class DepartmentDto {
private Long id;
private String departmentName;
private String departmentDescription;
}
DepartmentMapper
import net.javaguides.ems.dto.DepartmentDto;
import net.javaguides.ems.entity.Department;
public class DepartmentMapper {
// convert department jpa entity into department dto
public static DepartmentDto mapToDepartmentDto(Department department){
return new DepartmentDto(
department.getId(),
department.getDepartmentName(),
department.getDepartmentDescription()
);
}
// convert department dto into department jpa entity
public static Department mapToDepartment(DepartmentDto departmentDto){
return new Department(
departmentDto.getId(),
departmentDto.getDepartmentName(),
departmentDto.getDepartmentDescription()
);
}
}
ResourceNotFoundException
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException{
public ResourceNotFoundException(String message){
super(message);
}
}
6. Service Layer
Let's create a DepartmentService interface with the following CRUD methods:
DepartmentService
import net.javaguides.ems.dto.DepartmentDto;
import java.util.List;
public interface DepartmentService {
DepartmentDto createDepartment(DepartmentDto departmentDto);
DepartmentDto getDepartmentById(Long departmentId);
List<DepartmentDto> getAllDepartments();
DepartmentDto updateDepartment(Long departmentId, DepartmentDto updatedDepartment);
void deleteDepartment(Long departmentId);
}
DepartmentServiceImpl
import lombok.AllArgsConstructor;
import net.javaguides.ems.dto.DepartmentDto;
import net.javaguides.ems.entity.Department;
import net.javaguides.ems.exception.ResourceNotFoundException;
import net.javaguides.ems.mapper.DepartmentMapper;
import net.javaguides.ems.repository.DepartmentRepository;
import net.javaguides.ems.service.DepartmentService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@AllArgsConstructor
public class DepartmentServiceImpl implements DepartmentService {
private DepartmentRepository departmentRepository;
@Override
public DepartmentDto createDepartment(DepartmentDto departmentDto) {
Department department = DepartmentMapper.mapToDepartment(departmentDto);
Department savedDepartment = departmentRepository.save(department);
return DepartmentMapper.mapToDepartmentDto(savedDepartment);
}
@Override
public DepartmentDto getDepartmentById(Long departmentId) {
Department department = departmentRepository.findById(departmentId).orElseThrow(
() -> new ResourceNotFoundException("Department is not exists with a given id: " + departmentId)
);
return DepartmentMapper.mapToDepartmentDto(department);
}
@Override
public List<DepartmentDto> getAllDepartments() {
List<Department> departments = departmentRepository.findAll();
return departments.stream().map((department) -> DepartmentMapper.mapToDepartmentDto(department))
.collect(Collectors.toList());
}
@Override
public DepartmentDto updateDepartment(Long departmentId, DepartmentDto updatedDepartment) {
Department department = departmentRepository.findById(departmentId).orElseThrow(
() -> new ResourceNotFoundException("Department is not exists with a given id:"+ departmentId)
);
department.setDepartmentName(updatedDepartment.getDepartmentName());
department.setDepartmentDescription(updatedDepartment.getDepartmentDescription());
Department savedDepartment = departmentRepository.save(department);
return DepartmentMapper.mapToDepartmentDto(savedDepartment);
}
@Override
public void deleteDepartment(Long departmentId) {
departmentRepository.findById(departmentId).orElseThrow(
() -> new ResourceNotFoundException("Department is not exists with a given id: " + departmentId)
);
departmentRepository.deleteById(departmentId);
}
}
7. DepartmentController
Let's create a DepartmentController class that handles HTTP requests and delegates calls to the DepartmentServiceImpl class.
import lombok.AllArgsConstructor;
import net.javaguides.ems.dto.DepartmentDto;
import net.javaguides.ems.service.DepartmentService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@CrossOrigin("*")
@AllArgsConstructor
@RestController
@RequestMapping("/api/departments")
public class DepartmentController {
private DepartmentService departmentService;
// Build Create or Add Department REST API
@PostMapping
public ResponseEntity<DepartmentDto> createDepartment(@RequestBody DepartmentDto departmentDto){
DepartmentDto department = departmentService.createDepartment(departmentDto);
return new ResponseEntity<>(department, HttpStatus.CREATED);
}
// Build Get Department REST API
@GetMapping("{id}")
public ResponseEntity<DepartmentDto> getDepartmentById(@PathVariable("id") Long departmentId){
DepartmentDto departmentDto = departmentService.getDepartmentById(departmentId);
return ResponseEntity.ok(departmentDto);
}
// Build Get All Departments REST API
@GetMapping
public ResponseEntity<List<DepartmentDto>> getAllDepartments(){
List<DepartmentDto> departments = departmentService.getAllDepartments();
return ResponseEntity.ok(departments);
}
// Build Update Department REST API
@PutMapping("{id}")
public ResponseEntity<DepartmentDto> updateDepartment(@PathVariable("id") Long departmentId,
@RequestBody DepartmentDto updatedDepartment){
DepartmentDto departmentDto = departmentService.updateDepartment(departmentId, updatedDepartment);
return ResponseEntity.ok(departmentDto);
}
// Build Delete Department REST API
@DeleteMapping("{id}")
public ResponseEntity<String> deleteDepartment(@PathVariable("id") Long departmentId){
departmentService.deleteDepartment(departmentId);
return ResponseEntity.ok("Department deleted successfully!.");
}
}
8. Test CRUD REST APIs using Postman Client
Add Department REST API:
Get Department REST API:
Get All Departments REST API:Update Department REST API:
Delete Department REST API:
Conclusion
In this tutorial, we created a Spring Boot application that uses a DAO (Data Access Object) pattern. Basically, we performed CRUD operations with the MySQL database using the DAO pattern in the Spring boot project.
Comments
Post a Comment
Leave Comment