diff --git a/.gitignore b/.gitignore index 1901201..d7884b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.idea/ +target/ # Default ignored files /shelf/ /.idea/workspace.xml diff --git a/pom.xml b/pom.xml index 48b39fd..5391f43 100644 --- a/pom.xml +++ b/pom.xml @@ -29,6 +29,9 @@ 17 checkstyle.xml + 1.18.30 + 0.2.0 + 1.5.5.Final @@ -77,6 +80,25 @@ h2 test + + org.springframework.boot + spring-boot-starter-web + + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + provided + + + @@ -85,12 +107,25 @@ org.apache.maven.plugins maven-compiler-plugin - - - org.projectlombok - lombok - - + ${java.version} + ${java.version} + + + org.projectlombok + lombok + ${lombok.version} + + + org.projectlombok + lombok-mapstruct-binding + ${lombok.mapstruct.binding.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + @@ -110,6 +145,7 @@ true true false + src/main diff --git a/spring-boot-intro (1).iml b/spring-boot-intro (1).iml new file mode 100644 index 0000000..95df0ad --- /dev/null +++ b/spring-boot-intro (1).iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/boot/BootIntroApplication.java b/src/main/java/boot/BootIntroApplication.java index 0739a11..9a51151 100644 --- a/src/main/java/boot/BootIntroApplication.java +++ b/src/main/java/boot/BootIntroApplication.java @@ -29,7 +29,6 @@ public CommandLineRunner init(BookService bookService) { book.setPrice(new BigDecimal("19.99")); book.setCoverImage("https://example.com/cover.jpg"); - bookService.save(book); System.out.println(bookService.findAll()); }; } diff --git a/src/main/java/boot/config/MapperConfig.java b/src/main/java/boot/config/MapperConfig.java new file mode 100644 index 0000000..5fc527e --- /dev/null +++ b/src/main/java/boot/config/MapperConfig.java @@ -0,0 +1,14 @@ +package boot.config; + +import org.mapstruct.InjectionStrategy; +import org.mapstruct.NullValueCheckStrategy; + +@org.mapstruct.MapperConfig( + componentModel = "spring", + injectionStrategy = InjectionStrategy.CONSTRUCTOR, + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + implementationPackage = ".impl" +) +public class MapperConfig { + +} diff --git a/src/main/java/boot/controller/BookController.java b/src/main/java/boot/controller/BookController.java new file mode 100644 index 0000000..545b685 --- /dev/null +++ b/src/main/java/boot/controller/BookController.java @@ -0,0 +1,37 @@ +package boot.controller; + +import boot.dto.BookDto; +import boot.dto.CreateBookRequestDto; +import boot.service.BookService; +import java.util.List; +import lombok.RequiredArgsConstructor; +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.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RestController +@RequestMapping("/books") +public class BookController { + private final BookService bookService; + + @GetMapping + public List getAll() { + return bookService.findAll(); + } + + @GetMapping("/{id}") + @ResponseBody + public BookDto getBookById(@PathVariable Long id) { + return bookService.findById(id); + } + + @PostMapping + public BookDto createBook(@RequestBody CreateBookRequestDto bookDto) { + return bookService.save(bookDto); + } +} diff --git a/src/main/java/boot/dto/BookDto.java b/src/main/java/boot/dto/BookDto.java new file mode 100644 index 0000000..1a40884 --- /dev/null +++ b/src/main/java/boot/dto/BookDto.java @@ -0,0 +1,13 @@ +package boot.dto; + +import lombok.Data; + +@Data +public class BookDto { + private Long id; + private String title; + private String author; + private Double price; + private String description; + private String coverImage; +} diff --git a/src/main/java/boot/dto/CreateBookRequestDto.java b/src/main/java/boot/dto/CreateBookRequestDto.java new file mode 100644 index 0000000..b149603 --- /dev/null +++ b/src/main/java/boot/dto/CreateBookRequestDto.java @@ -0,0 +1,14 @@ +package boot.dto; + +import lombok.Data; + +@Data +public class CreateBookRequestDto { + private Long id; + private String title; + private String author; + private String isbn; + private Double price; + private String description; + private String coverImage; +} diff --git a/src/main/java/boot/exception/EntityNotFoundException.java b/src/main/java/boot/exception/EntityNotFoundException.java new file mode 100644 index 0000000..5b9fcad --- /dev/null +++ b/src/main/java/boot/exception/EntityNotFoundException.java @@ -0,0 +1,7 @@ +package boot.exception; + +public class EntityNotFoundException extends RuntimeException { + public EntityNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/boot/mapper/BookMapper.java b/src/main/java/boot/mapper/BookMapper.java new file mode 100644 index 0000000..ee8646b --- /dev/null +++ b/src/main/java/boot/mapper/BookMapper.java @@ -0,0 +1,14 @@ +package boot.mapper; + +import boot.config.MapperConfig; +import boot.dto.BookDto; +import boot.dto.CreateBookRequestDto; +import boot.model.Book; +import org.mapstruct.Mapper; + +@Mapper(config = MapperConfig.class) +public interface BookMapper { + BookDto toBookDto(Book book); + + Book toBook(CreateBookRequestDto bookDto); +} diff --git a/src/main/java/boot/repository/BookRepository.java b/src/main/java/boot/repository/BookRepository.java index d2d06b7..5395c1b 100644 --- a/src/main/java/boot/repository/BookRepository.java +++ b/src/main/java/boot/repository/BookRepository.java @@ -2,9 +2,12 @@ import boot.model.Book; import java.util.List; +import java.util.Optional; public interface BookRepository { Book save(Book book); List findAll(); + + Optional findById(Long id); } diff --git a/src/main/java/boot/repository/BookRepositoryImpl.java b/src/main/java/boot/repository/BookRepositoryImpl.java index 9eb40be..3ef4e27 100644 --- a/src/main/java/boot/repository/BookRepositoryImpl.java +++ b/src/main/java/boot/repository/BookRepositoryImpl.java @@ -3,6 +3,7 @@ import boot.exception.DataProcessingException; import boot.model.Book; import java.util.List; +import java.util.Optional; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; @@ -48,4 +49,13 @@ public List findAll() { throw new DataProcessingException("Could not find all books", e); } } + + @Override + public Optional findById(Long id) { + try (Session session = sessionFactory.openSession()) { + return Optional.ofNullable(session.get(Book.class, id)); + } catch (Exception e) { + throw new DataProcessingException("Could not find book with id: " + id, e); + } + } } diff --git a/src/main/java/boot/service/BookService.java b/src/main/java/boot/service/BookService.java index 79337af..954aed0 100644 --- a/src/main/java/boot/service/BookService.java +++ b/src/main/java/boot/service/BookService.java @@ -1,10 +1,13 @@ package boot.service; -import boot.model.Book; +import boot.dto.BookDto; +import boot.dto.CreateBookRequestDto; import java.util.List; public interface BookService { - Book save(Book book); + BookDto save(CreateBookRequestDto bookDto); - List findAll(); + List findAll(); + + BookDto findById(Long id); } diff --git a/src/main/java/boot/service/BookServiceImpl.java b/src/main/java/boot/service/BookServiceImpl.java index d0c0f72..fd63317 100644 --- a/src/main/java/boot/service/BookServiceImpl.java +++ b/src/main/java/boot/service/BookServiceImpl.java @@ -1,25 +1,40 @@ package boot.service; +import boot.dto.BookDto; +import boot.dto.CreateBookRequestDto; +import boot.exception.EntityNotFoundException; +import boot.mapper.BookMapper; import boot.model.Book; import boot.repository.BookRepository; import java.util.List; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class BookServiceImpl implements BookService { - @Autowired private final BookRepository bookRepository; + private final BookMapper bookMapper; + + @Override + public BookDto save(CreateBookRequestDto bookDto) { + Book book = bookMapper.toBook(bookDto); + return bookMapper.toBookDto(bookRepository.save(book)); + } + @Override - public Book save(Book book) { - return bookRepository.save(book); + public List findAll() { + return bookRepository.findAll().stream() + .map(bookMapper::toBookDto) + .toList(); } @Override - public List findAll() { - return bookRepository.findAll(); + public BookDto findById(Long id) { + Book book = bookRepository.findById(id).orElseThrow(() -> new EntityNotFoundException( + "Can't find Book with id:" + id) + ); + return bookMapper.toBookDto(book); } }