In this tutorial, we will learn how to use DTO (Data Transfer Object) pattern in Spring Boot application.
Martin Fowler describes the Data Transfer Object in his famous book Patterns of Enterprise Application Architecture. There, the main idea of DTOs is to reduce the number of remote calls that are expensive.In Java applications - we use JPA entity classes to represent tables in a relational database. Without DTOs, we'd have to expose the entire entities to a remote interface. This causes a strong coupling between an API and a persistence model.
By using a DTO to transfer just the required information, we loosen the coupling between the API and our model, allowing us to more easily maintain and scale the service.
- Java 11
- Spring Boot
- Spring Data JPA (Hibernate)
- H2 in-memory database
- Maven
- Lombok
- Eclipse STS IDE
We’ll use Spring initializr web tool to bootstrap our application.
Go to http://start.spring.io
Select Java in the language section.
Enter Artifact as spring-dto-tutorial
Add Spring Web, Lombok, Spring Data JPA, and H2 dependencies.
Click Generate to generate and download the project.
Once the project is generated, unzip it and import it into your favorite IDE.
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>net.javaguides</groupId>
<artifactId>springboot-dto-tutorial</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-dto-tutorial</name>
<description>Demo project for Spring Boot and DTO</description>
<properties>
<java.version>11</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>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.modelmapper/modelmapper -->
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.4.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
package net.javaguides.springboot.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String email;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
private String password;
@ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "location_id")
private Location location;
}
package net.javaguides.springboot.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "locations")
public class Location {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String place;
private String description;
private double longitude;
private double latitude;
}
package net.javaguides.springboot.repository;
import net.javaguides.springboot.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
package net.javaguides.springboot.repository;
import net.javaguides.springboot.model.Location;
import org.springframework.data.jpa.repository.JpaRepository;
public interface LocationRepository extends JpaRepository<Location, Long> {
}
package net.javaguides.springboot.dto;
import lombok.Data;
@Data
public class UserLocationDTO {
private long userId;
private String email;
private String place;
private double longitude;
private double latitude;
}
package net.javaguides.springboot.service;
import net.javaguides.springboot.dto.UserLocationDTO;
import net.javaguides.springboot.model.User;
import net.javaguides.springboot.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<UserLocationDTO> getAllUsersLocation(){
return userRepository.findAll()
.stream()
.map(this::convertEntityToDto)
.collect(Collectors.toList());
}
private UserLocationDTO convertEntityToDto(User user){
UserLocationDTO userLocationDTO = new UserLocationDTO();
userLocationDTO.setUserId(user.getId());
userLocationDTO.setEmail(user.getEmail());
userLocationDTO.setPlace(user.getLocation().getPlace());
userLocationDTO.setLongitude(user.getLocation().getLongitude());
userLocationDTO.setLatitude(user.getLocation().getLatitude());
return userLocationDTO;
}
}
package net.javaguides.springboot.controller;
import net.javaguides.springboot.dto.UserLocationDTO;
import net.javaguides.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users-location")
public List<UserLocationDTO> getAllUsersLocation(){
return userService.getAllUsersLocation();
}
}
package net.javaguides.springboot;
import net.javaguides.springboot.model.Location;
import net.javaguides.springboot.model.User;
import net.javaguides.springboot.repository.LocationRepository;
import net.javaguides.springboot.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class SpringbootDtoTutorialApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(SpringbootDtoTutorialApplication.class, args);
}
@Autowired
private UserRepository userRepository;
@Autowired
private LocationRepository locationRepository;
@Override
public void run(String... args) throws Exception {
Location location = new Location();
location.setPlace("Pune");
location.setDescription("Pune is great place to live");
location.setLongitude(40.5);
location.setLatitude(30.6);
locationRepository.save(location);
User user1 = new User();
user1.setFirstName("Ramesh");
user1.setLastName("Fadatare");
user1.setEmail("ramesh@gmail.com");
user1.setPassword("secret");
user1.setLocation(location);
userRepository.save(user1);
User user2 = new User();
user2.setFirstName("John");
user2.setLastName("Cena");
user2.setEmail("john@gmail.com");
user2.setPassword("secret");
user2.setLocation(location);
userRepository.save(user2);
}
}
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.
Hit below URL in browser to get response of the REST API:
http://localhost:8080/users-location
Comments
Post a Comment