Merge pull request #15225 from ovidiumihaitacu/master
[BAEL-7067] Difference Between Entity and DTO
This commit is contained in:
commit
93ebe9cda7
|
@ -0,0 +1,12 @@
|
|||
package com.baeldung.entitydtodifferences;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.baeldung.entitydtodifferences.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.entitydtodifferences.dto.UserCreationDto;
|
||||
import com.baeldung.entitydtodifferences.dto.UserResponseDto;
|
||||
import com.baeldung.entitydtodifferences.mapper.UserMapper;
|
||||
import com.baeldung.entitydtodifferences.repository.UserRepository;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/users")
|
||||
public class UserController {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public UserController(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<UserResponseDto> getUsers() {
|
||||
return userRepository.findAll()
|
||||
.stream()
|
||||
.map(UserMapper::toDto)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public UserResponseDto createUser(@RequestBody UserCreationDto userCreationDto) {
|
||||
return UserMapper.toDto(userRepository.save(UserMapper.toEntity(userCreationDto)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.baeldung.entitydtodifferences.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class BookDto {
|
||||
|
||||
@JsonProperty("NAME")
|
||||
private final String name;
|
||||
|
||||
@JsonProperty("AUTHOR")
|
||||
private final String author;
|
||||
|
||||
// Default constructor for Jackson deserialization
|
||||
public BookDto() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public BookDto(String name, String author) {
|
||||
this.name = name;
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.baeldung.entitydtodifferences.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class UserCreationDto {
|
||||
|
||||
@JsonProperty("FIRST_NAME")
|
||||
private final String firstName;
|
||||
|
||||
@JsonProperty("LAST_NAME")
|
||||
private final String lastName;
|
||||
|
||||
@JsonProperty("ADDRESS")
|
||||
private final String address;
|
||||
|
||||
@JsonProperty("BOOKS")
|
||||
private final List<BookDto> books;
|
||||
|
||||
// Default constructor for Jackson deserialization
|
||||
public UserCreationDto() {
|
||||
this(null, null, null, null);
|
||||
}
|
||||
|
||||
public UserCreationDto(String firstName, String lastName, String address, List<BookDto> books) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.address = address;
|
||||
this.books = books;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public List<BookDto> getBooks() {
|
||||
return books;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.baeldung.entitydtodifferences.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class UserResponseDto {
|
||||
|
||||
@JsonProperty("ID")
|
||||
private final Long id;
|
||||
|
||||
@JsonProperty("FIRST_NAME")
|
||||
private final String firstName;
|
||||
|
||||
@JsonProperty("LAST_NAME")
|
||||
private final String lastName;
|
||||
|
||||
@JsonProperty("BOOKS")
|
||||
private final List<BookDto> books;
|
||||
|
||||
// Default constructor for Jackson deserialization
|
||||
public UserResponseDto() {
|
||||
this(null, null, null, null);
|
||||
}
|
||||
|
||||
public UserResponseDto(Long id, String firstName, String lastName, List<BookDto> books) {
|
||||
this.id = id;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.books = books;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public List<BookDto> getBooks() {
|
||||
return books;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.baeldung.entitydtodifferences.entity;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "books")
|
||||
public class Book {
|
||||
|
||||
@Id
|
||||
private String name;
|
||||
private String author;
|
||||
|
||||
// Default constructor for JPA deserialization
|
||||
public Book() {
|
||||
}
|
||||
|
||||
public Book(String name, String author) {
|
||||
this.name = name;
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package com.baeldung.entitydtodifferences.entity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String address;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL)
|
||||
private List<Book> books;
|
||||
|
||||
// Default constructor for JPA deserialization
|
||||
public User() {
|
||||
}
|
||||
|
||||
public User(String firstName, String lastName, String address, List<Book> books) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.address = address;
|
||||
this.books = books;
|
||||
}
|
||||
|
||||
public String getNameOfMostOwnedBook() {
|
||||
Map<String, Long> bookOwnershipCount = books.stream()
|
||||
.collect(Collectors.groupingBy(Book::getName, Collectors.counting()));
|
||||
return bookOwnershipCount.entrySet()
|
||||
.stream()
|
||||
.max(Map.Entry.comparingByValue())
|
||||
.map(Map.Entry::getKey)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long 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 getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public List<Book> getBooks() {
|
||||
return books;
|
||||
}
|
||||
|
||||
public void setBooks(List<Book> books) {
|
||||
this.books = books;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.entitydtodifferences.mapper;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.baeldung.entitydtodifferences.dto.BookDto;
|
||||
import com.baeldung.entitydtodifferences.dto.UserCreationDto;
|
||||
import com.baeldung.entitydtodifferences.dto.UserResponseDto;
|
||||
import com.baeldung.entitydtodifferences.entity.Book;
|
||||
import com.baeldung.entitydtodifferences.entity.User;
|
||||
|
||||
public class UserMapper {
|
||||
|
||||
public static UserResponseDto toDto(User entity) {
|
||||
return new UserResponseDto(entity.getId(), entity.getFirstName(), entity.getLastName(), entity.getBooks()
|
||||
.stream()
|
||||
.map(UserMapper::toDto)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public static User toEntity(UserCreationDto dto) {
|
||||
return new User(dto.getFirstName(), dto.getLastName(), dto.getAddress(), dto.getBooks()
|
||||
.stream()
|
||||
.map(UserMapper::toEntity)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public static BookDto toDto(Book entity) {
|
||||
return new BookDto(entity.getName(), entity.getAuthor());
|
||||
}
|
||||
|
||||
public static Book toEntity(BookDto dto) {
|
||||
return new Book(dto.getName(), dto.getAuthor());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.entitydtodifferences.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.baeldung.entitydtodifferences.entity.User;
|
||||
|
||||
@Repository
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.entitydtodifferences;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class ApplicationIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package com.baeldung.entitydtodifferences.controller;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import com.baeldung.entitydtodifferences.entity.Book;
|
||||
import com.baeldung.entitydtodifferences.entity.User;
|
||||
import com.baeldung.entitydtodifferences.repository.UserRepository;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
public class UserControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEach() {
|
||||
userRepository.deleteAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUsersAreExisting_whenGetUsers_thenUsersAreReturned() throws Exception {
|
||||
//given
|
||||
Book book1 = new Book("Book1", "Author1");
|
||||
Book book2 = new Book("Book2", "Author2");
|
||||
User savedUser = userRepository.save(new User("John", "Doe", "123 Main St", Arrays.asList(book1, book2)));
|
||||
String expectedJson = String.format(
|
||||
"[{\"ID\":%s,\"FIRST_NAME\":\"John\",\"LAST_NAME\":\"Doe\",\"BOOKS\":[{\"NAME\":\"Book1\",\"AUTHOR\":\"Author1\"},{\"NAME\":\"Book2\",\"AUTHOR\":\"Author2\"}]}]",
|
||||
savedUser.getId());
|
||||
//when
|
||||
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/users")
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andReturn();
|
||||
//then
|
||||
assertEquals(expectedJson, result.getResponse()
|
||||
.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenValidUser_whenPostUser_thenUserIsCreated() throws Exception {
|
||||
//given
|
||||
String user = "{\"FIRST_NAME\":\"John\",\"LAST_NAME\":\"Doe\",\"BOOKS\":[{\"NAME\":\"Book1\",\"AUTHOR\":\"Author1\"},{\"NAME\":\"Book2\",\"AUTHOR\":\"Author2\"}]}";
|
||||
//when
|
||||
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/users")
|
||||
.content(user)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andReturn();
|
||||
JsonNode responseJson = objectMapper.readTree(result.getResponse()
|
||||
.getContentAsString());
|
||||
//then
|
||||
assertEquals("John", responseJson.get("FIRST_NAME")
|
||||
.asText());
|
||||
assertEquals("Doe", responseJson.get("LAST_NAME")
|
||||
.asText());
|
||||
assertTrue(responseJson.has("BOOKS"));
|
||||
JsonNode booksArray = responseJson.get("BOOKS");
|
||||
assertEquals(2, booksArray.size());
|
||||
assertEquals("Book1", booksArray.get(0)
|
||||
.get("NAME")
|
||||
.asText());
|
||||
assertEquals("Author1", booksArray.get(0)
|
||||
.get("AUTHOR")
|
||||
.asText());
|
||||
assertEquals("Book2", booksArray.get(1)
|
||||
.get("NAME")
|
||||
.asText());
|
||||
assertEquals("Author2", booksArray.get(1)
|
||||
.get("AUTHOR")
|
||||
.asText());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.entitydtodifferences.entity;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class BookUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenBookInitialized_thenInitializedCorrectly() {
|
||||
//when
|
||||
Book book = new Book("Book1", "Author1");
|
||||
//then
|
||||
assertNotNull(book);
|
||||
assertEquals("Book1", book.getName());
|
||||
assertEquals("Author1", book.getAuthor());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.baeldung.entitydtodifferences.entity;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class UserUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenUserInitialized_thenInitializedCorrectly() {
|
||||
//when
|
||||
Book book1 = new Book("Book1", "Author1");
|
||||
Book book2 = new Book("Book2", "Author2");
|
||||
User user = new User("John", "Doe", "123 Main St", Arrays.asList(book1, book2));
|
||||
//then
|
||||
assertNotNull(user);
|
||||
assertEquals("John", user.getFirstName());
|
||||
assertEquals("Doe", user.getLastName());
|
||||
assertEquals("123 Main St", user.getAddress());
|
||||
assertEquals(2, user.getBooks()
|
||||
.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUserOwningMultipleBooks_whenGetNameOfMostOwnedBook_thenComputedCorrectly() {
|
||||
//given
|
||||
Book book1 = new Book("Book1", "Author1");
|
||||
Book book2 = new Book("Book2", "Author2");
|
||||
Book book3 = new Book("Book2", "Author3");
|
||||
User user = new User("John", "Doe", "123 Main St", Arrays.asList(book1, book2, book3));
|
||||
//when
|
||||
String mostOwnedBook = user.getNameOfMostOwnedBook();
|
||||
//then
|
||||
assertEquals("Book2", mostOwnedBook);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUserWithNoBooks_henGetNameOfMostOwnedBook_thenReturnedNull() {
|
||||
//given
|
||||
User user = new User("John", "Doe", "123 Main St", Collections.emptyList());
|
||||
//when
|
||||
String mostOwnedBook = user.getNameOfMostOwnedBook();
|
||||
//then
|
||||
assertNull(mostOwnedBook);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package com.baeldung.entitydtodifferences.mapper;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.entitydtodifferences.dto.BookDto;
|
||||
import com.baeldung.entitydtodifferences.dto.UserCreationDto;
|
||||
import com.baeldung.entitydtodifferences.dto.UserResponseDto;
|
||||
import com.baeldung.entitydtodifferences.entity.Book;
|
||||
import com.baeldung.entitydtodifferences.entity.User;
|
||||
|
||||
public class UserMapperUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenUserEntity_whenMappedToDto_thenMappedCorrectly() {
|
||||
//given
|
||||
Book book1 = new Book("Book1", "Author1");
|
||||
Book book2 = new Book("Book2", "Author2");
|
||||
User user = new User("John", "Doe", "123 Main St", Arrays.asList(book1, book2));
|
||||
//when
|
||||
UserResponseDto userDto = UserMapper.toDto(user);
|
||||
//then
|
||||
assertEquals(user.getId(), userDto.getId());
|
||||
assertEquals(user.getFirstName(), userDto.getFirstName());
|
||||
assertEquals(user.getLastName(), userDto.getLastName());
|
||||
List<BookDto> bookDtos = userDto.getBooks();
|
||||
assertEquals(2, bookDtos.size());
|
||||
assertEquals(book1.getName(), bookDtos.get(0)
|
||||
.getName());
|
||||
assertEquals(book1.getAuthor(), bookDtos.get(0)
|
||||
.getAuthor());
|
||||
assertEquals(book2.getName(), bookDtos.get(1)
|
||||
.getName());
|
||||
assertEquals(book2.getAuthor(), bookDtos.get(1)
|
||||
.getAuthor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUserDto_whenMappedToEntity_thenMappedCorrectly() {
|
||||
//given
|
||||
BookDto bookDto1 = new BookDto("Book3", "Author3");
|
||||
BookDto bookDto2 = new BookDto("Book4", "Author4");
|
||||
UserCreationDto userDto = new UserCreationDto("Jane", "Doe", "456 Oak St", Arrays.asList(bookDto1, bookDto2));
|
||||
//when
|
||||
User user = UserMapper.toEntity(userDto);
|
||||
//then
|
||||
assertEquals(user.getFirstName(), userDto.getFirstName());
|
||||
assertEquals(user.getLastName(), userDto.getLastName());
|
||||
assertEquals(user.getAddress(), userDto.getAddress());
|
||||
List<Book> books = user.getBooks();
|
||||
assertEquals(2, books.size());
|
||||
assertEquals(bookDto1.getName(), books.get(0)
|
||||
.getName());
|
||||
assertEquals(bookDto1.getAuthor(), books.get(0)
|
||||
.getAuthor());
|
||||
assertEquals(bookDto2.getName(), books.get(1)
|
||||
.getName());
|
||||
assertEquals(bookDto2.getAuthor(), books.get(1)
|
||||
.getAuthor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBookEntity_whenMappedToDto_thenMappedCorrectly() {
|
||||
//given
|
||||
Book book = new Book("Book5", "Author5");
|
||||
//when
|
||||
BookDto bookDto = UserMapper.toDto(book);
|
||||
//then
|
||||
assertEquals(book.getName(), bookDto.getName());
|
||||
assertEquals(book.getAuthor(), bookDto.getAuthor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBookDto_whenMappedToEntity_thenMappedCorrectly() {
|
||||
//given
|
||||
BookDto bookDto = new BookDto("Book6", "Author6");
|
||||
//when
|
||||
Book book = UserMapper.toEntity(bookDto);
|
||||
//then
|
||||
assertEquals(bookDto.getName(), book.getName());
|
||||
assertEquals(bookDto.getAuthor(), book.getAuthor());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue