From 12cbfffc397740c5618b4b89124ff902aecec182 Mon Sep 17 00:00:00 2001 From: Vyacheslav Date: Sat, 14 Oct 2023 12:44:52 +0300 Subject: [PATCH] Added Book model, repository & service layers --- pom.xml | 36 +++++++- .../org/bookstore/JvBookStoreApplication.java | 22 +++++ .../java/org/bookstore/config/AppConfig.java | 43 +++++++++ .../exceptions/DataProcessingException.java | 11 +++ src/main/java/org/bookstore/model/Book.java | 92 +++++++++++++++++++ .../bookstore/repository/BookRepository.java | 11 +++ .../repository/impl/BookRepositoryImpl.java | 46 ++++++++++ .../org/bookstore/service/BookService.java | 10 ++ .../service/impl/BookServiceImpl.java | 29 ++++++ src/main/resources/application.properties | 7 +- src/test/resources/application.properties | 5 + 11 files changed, 309 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/bookstore/config/AppConfig.java create mode 100644 src/main/java/org/bookstore/exceptions/DataProcessingException.java create mode 100644 src/main/java/org/bookstore/model/Book.java create mode 100644 src/main/java/org/bookstore/repository/BookRepository.java create mode 100644 src/main/java/org/bookstore/repository/impl/BookRepositoryImpl.java create mode 100644 src/main/java/org/bookstore/service/BookService.java create mode 100644 src/main/java/org/bookstore/service/impl/BookServiceImpl.java create mode 100644 src/test/resources/application.properties diff --git a/pom.xml b/pom.xml index d89de51..2116845 100644 --- a/pom.xml +++ b/pom.xml @@ -20,14 +20,46 @@ org.springframework.boot - spring-boot-starter + spring-boot-starter-web + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.hibernate + hibernate-core + 6.3.1.Final - org.springframework.boot spring-boot-starter-test test + + com.h2database + h2 + 2.2.224 + test + + + org.springframework + spring-orm + 6.0.11 + + + org.apache.commons + commons-dbcp2 + 2.9.0 + + + com.mysql + mysql-connector-j + 8.0.33 + + diff --git a/src/main/java/org/bookstore/JvBookStoreApplication.java b/src/main/java/org/bookstore/JvBookStoreApplication.java index f79229e..50d61e0 100644 --- a/src/main/java/org/bookstore/JvBookStoreApplication.java +++ b/src/main/java/org/bookstore/JvBookStoreApplication.java @@ -1,13 +1,35 @@ package org.bookstore; +import java.math.BigDecimal; +import org.bookstore.model.Book; +import org.bookstore.service.BookService; +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 JvBookStoreApplication { + @Autowired + private BookService bookService; + public static void main(String[] args) { SpringApplication.run(JvBookStoreApplication.class, args); } + @Bean + public CommandLineRunner commandLineRunner(BookService bookService) { + return args -> { + Book book = new Book(); + book.setAuthor("Author"); + book.setDescription("Description"); + book.setPrice(BigDecimal.ZERO); + book.setTitle("Title"); + book.setIsbn("ISBN"); + bookService.save(book); + bookService.findAll().forEach(System.out::println); + }; + } } diff --git a/src/main/java/org/bookstore/config/AppConfig.java b/src/main/java/org/bookstore/config/AppConfig.java new file mode 100644 index 0000000..2a7a474 --- /dev/null +++ b/src/main/java/org/bookstore/config/AppConfig.java @@ -0,0 +1,43 @@ +package org.bookstore.config; + +import java.util.Properties; +import javax.sql.DataSource; +import org.apache.commons.dbcp2.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; + +@Configuration +@ComponentScan(basePackages = "org.bookstore") +@PropertySource("classpath:application.properties") +public class AppConfig { + @Autowired + private Environment environment; + + @Bean + public DataSource getDataSource() { + BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(environment.getProperty("db.driver-class-name")); + dataSource.setUrl(environment.getProperty("db.url")); + dataSource.setUsername(environment.getProperty("db.username")); + dataSource.setPassword(environment.getProperty("db.password")); + return dataSource; + } + + @Bean + public LocalSessionFactoryBean sessionFactory() { + LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean(); + sessionFactoryBean.setDataSource(getDataSource()); + sessionFactoryBean.setPackagesToScan("org.bookstore"); + Properties properties = new Properties(); + properties.put("show_sql", "true"); + properties.put("hibernate.hbm2ddl.auto", "create-drop"); + properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect"); + sessionFactoryBean.setHibernateProperties(properties); + return sessionFactoryBean; + } +} diff --git a/src/main/java/org/bookstore/exceptions/DataProcessingException.java b/src/main/java/org/bookstore/exceptions/DataProcessingException.java new file mode 100644 index 0000000..92aeb97 --- /dev/null +++ b/src/main/java/org/bookstore/exceptions/DataProcessingException.java @@ -0,0 +1,11 @@ +package org.bookstore.exceptions; + +public class DataProcessingException extends RuntimeException { + public DataProcessingException(String message) { + super(message); + } + + public DataProcessingException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/bookstore/model/Book.java b/src/main/java/org/bookstore/model/Book.java new file mode 100644 index 0000000..8b02dcf --- /dev/null +++ b/src/main/java/org/bookstore/model/Book.java @@ -0,0 +1,92 @@ +package org.bookstore.model; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import java.math.BigDecimal; + +@Entity +public class Book { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @Column(nullable = false) + private String title; + @Column(nullable = false) + private String author; + @Column(nullable = false, unique = true) + private String isbn; + @Column(nullable = false) + private BigDecimal price; + private String description; + private String coverImage; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getCoverImage() { + return coverImage; + } + + public void setCoverImage(String coverImage) { + this.coverImage = coverImage; + } + + @Override + public String toString() { + return "Book{" + + "id=" + id + + ", title='" + title + '\'' + + ", author='" + author + '\'' + + ", isbn='" + isbn + '\'' + + ", price=" + price + + '}'; + } +} diff --git a/src/main/java/org/bookstore/repository/BookRepository.java b/src/main/java/org/bookstore/repository/BookRepository.java new file mode 100644 index 0000000..65f8aae --- /dev/null +++ b/src/main/java/org/bookstore/repository/BookRepository.java @@ -0,0 +1,11 @@ +package org.bookstore.repository; + +import java.util.List; +import org.bookstore.model.Book; + +public interface BookRepository { + + Book save(Book book); + + List findAll(); +} diff --git a/src/main/java/org/bookstore/repository/impl/BookRepositoryImpl.java b/src/main/java/org/bookstore/repository/impl/BookRepositoryImpl.java new file mode 100644 index 0000000..a55e9b6 --- /dev/null +++ b/src/main/java/org/bookstore/repository/impl/BookRepositoryImpl.java @@ -0,0 +1,46 @@ +package org.bookstore.repository.impl; + +import java.util.List; +import org.bookstore.exceptions.DataProcessingException; +import org.bookstore.model.Book; +import org.bookstore.repository.BookRepository; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class BookRepositoryImpl implements BookRepository { + private final SessionFactory sessionFactory; + + @Autowired + public BookRepositoryImpl(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + @Override + public Book save(Book book) { + Transaction transaction = null; + try (Session session = sessionFactory.openSession()) { + transaction = session.beginTransaction(); + session.persist(book); + transaction.commit(); + return book; + } catch (Exception e) { + if (transaction != null) { + transaction.rollback(); + } + throw new DataProcessingException("Can't save book " + book, e); + } + } + + @Override + public List findAll() { + try (Session session = sessionFactory.openSession()) { + return session.createQuery("from Book b", Book.class).getResultList(); + } catch (Exception e) { + throw new DataProcessingException("Can't get all books", e); + } + } +} diff --git a/src/main/java/org/bookstore/service/BookService.java b/src/main/java/org/bookstore/service/BookService.java new file mode 100644 index 0000000..09e9314 --- /dev/null +++ b/src/main/java/org/bookstore/service/BookService.java @@ -0,0 +1,10 @@ +package org.bookstore.service; + +import java.util.List; +import org.bookstore.model.Book; + +public interface BookService { + Book save(Book book); + + List findAll(); +} diff --git a/src/main/java/org/bookstore/service/impl/BookServiceImpl.java b/src/main/java/org/bookstore/service/impl/BookServiceImpl.java new file mode 100644 index 0000000..2a85347 --- /dev/null +++ b/src/main/java/org/bookstore/service/impl/BookServiceImpl.java @@ -0,0 +1,29 @@ +package org.bookstore.service.impl; + +import java.util.List; +import org.bookstore.model.Book; +import org.bookstore.repository.BookRepository; +import org.bookstore.service.BookService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class BookServiceImpl implements BookService { + + private final BookRepository bookRepository; + + @Autowired + public BookServiceImpl(BookRepository bookRepository) { + this.bookRepository = bookRepository; + } + + @Override + public Book save(Book book) { + return bookRepository.save(book); + } + + @Override + public List findAll() { + return bookRepository.findAll(); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8b13789..c9d5cfd 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,6 @@ - +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.show-sql=true +db.driver-class-name=com.mysql.cj.jdbc.Driver +db.url=jdbc:mysql://localhost:3306/db +db.username=slava +db.password=12345 diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..bc2fdde --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,5 @@ +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect