diff --git a/README.md b/README.md index e2cfdc7..0a53118 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,19 @@ # OtusSpringHW-Library -Домашние задания по Spring для Otus с базами данных. + +Домашнее задание #6: +- Переписать приложение для хранения книг на ORM. +- Использовать JPA, Hibernate только в качестве JPA-провайдера. +- Добавить комментарии к книгам, и высокоуровневые сервисы, оставляющие комментарии к книгам. +- Покрыть DAO тестами используя H2 базу данных и соответствующий H2 Hibernate-диалект. + +### 19-06-19 Доработки: +- Добавлены названия тэстов. +- Связи OneToOne изменены на ManyToOne. + +### 19-06-20 Доработки: +- Изменена струкрура запроса для сущности Book. + +### 19-06-22 Доработки: +- Добавлена сущность Comment. +- Изменение механизма добавления/обновления сущностей. +- Добавление классов для обработки сущности Comment и покрытие тестами. diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..f1fbb76 --- /dev/null +++ b/pom.xml @@ -0,0 +1,168 @@ + + + 4.0.0 + + home-work + + ru.otus.mkulikov + home-work + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + + + UTF-8 + + + + + net.sf.opencsv + opencsv + 2.3 + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + org.projectlombok + lombok + 1.18.4 + provided + + + + + junit + junit + 4.12 + test + + + + org.junit.jupiter + junit-jupiter-api + 5.3.2 + test + + + + org.junit.jupiter + junit-jupiter-engine + 5.3.2 + test + + + + org.junit.platform + junit-platform-launcher + 1.4.1 + test + + + + + org.mockito + mockito-all + 1.10.19 + test + + + + + org.springframework.boot + spring-boot-starter + + + + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.shell + spring-shell-starter + 2.0.0.RELEASE + + + + + com.h2database + h2 + 1.4.199 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.apache.maven.plugins + maven-resources-plugin + + ${encoding} + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.0 + + + false + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + src/main/resources + + **/*.csv + **/*.properties + **/*.txt + **/*.yml + **/*.sql + + false + + + + \ No newline at end of file diff --git a/src/main/java/ru/otus/mkulikov/Application.java b/src/main/java/ru/otus/mkulikov/Application.java new file mode 100644 index 0000000..005151d --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/Application.java @@ -0,0 +1,22 @@ +package ru.otus.mkulikov; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 15:27 + */ + +@SpringBootApplication +@EnableConfigurationProperties +public class Application { + + public static void main(String[] args) throws Exception { + SpringApplication.run(Application.class); + //Console.main(args); + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/dao/AuthorDao.java b/src/main/java/ru/otus/mkulikov/app/dao/AuthorDao.java new file mode 100644 index 0000000..6f09bc7 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/dao/AuthorDao.java @@ -0,0 +1,23 @@ +package ru.otus.mkulikov.app.dao; + +import ru.otus.mkulikov.app.model.Author; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 17:06 + */ + +public interface AuthorDao { + + T getById(long id); + + List getAllObjects(); + + int save(T t); + + int deleteObject(long id); +} diff --git a/src/main/java/ru/otus/mkulikov/app/dao/AuthorDaoJpa.java b/src/main/java/ru/otus/mkulikov/app/dao/AuthorDaoJpa.java new file mode 100644 index 0000000..9c8cdb4 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/dao/AuthorDaoJpa.java @@ -0,0 +1,64 @@ +package ru.otus.mkulikov.app.dao; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; +import ru.otus.mkulikov.app.model.Author; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 17:06 + */ + +@SuppressWarnings({"SqlNoDataSourceInspection", "ConstantConditions", "SqlDialectInspection"}) +@Repository +@Transactional +@RequiredArgsConstructor +public class AuthorDaoJpa implements AuthorDao { + + @PersistenceContext + private EntityManager em; + + @Override + public Author getById(long id) { + List list = em.createQuery("select a from Author a where a.id = :id", Author.class) + .setParameter("id", id) + .getResultList(); + + em.clear(); + return (list != null && !list.isEmpty()) ? list.get(0) : null; + } + + @Override + public List getAllObjects() { + List list = em.createQuery("select a from Author a order by a.id", Author.class) + .getResultList(); + + em.clear(); + return list; + } + + @Override + public int save(Author author) { + if (author.getId() == 0) { + em.persist(author); + } else { + em.merge(author); + } + System.out.println("Author saved with id: " + author.getId()); + return 1; + } + + @Override + public int deleteObject(long id) { + return em.createQuery("delete from Author a where a.id = :id ") + .setParameter("id", id) + .executeUpdate(); + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/dao/BookDao.java b/src/main/java/ru/otus/mkulikov/app/dao/BookDao.java new file mode 100644 index 0000000..58aaf0f --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/dao/BookDao.java @@ -0,0 +1,23 @@ +package ru.otus.mkulikov.app.dao; + +import ru.otus.mkulikov.app.model.Book; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 13:28 + */ + +public interface BookDao { + + T getById(long id); + + List getAllObjects(); + + int save(T t); + + int deleteObject(long id); +} diff --git a/src/main/java/ru/otus/mkulikov/app/dao/BookDaoJpa.java b/src/main/java/ru/otus/mkulikov/app/dao/BookDaoJpa.java new file mode 100644 index 0000000..dad9f26 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/dao/BookDaoJpa.java @@ -0,0 +1,75 @@ +package ru.otus.mkulikov.app.dao; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; +import ru.otus.mkulikov.app.model.Book; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 13:28 + */ + +@SuppressWarnings({"SqlNoDataSourceInspection", "ConstantConditions", "SqlDialectInspection"}) +@Repository +@Transactional +@RequiredArgsConstructor +public class BookDaoJpa implements BookDao { + + @PersistenceContext + private EntityManager em; + + @Override + public Book getById(long id) { + List books = em.createQuery("select distinct b " + + "from Book b " + + "inner join fetch b.author a " + + "inner join fetch b.genre g " + + "left join b.comments c " + + "where b.id = :id ", Book.class) + .setParameter("id", id) + .getResultList(); + + em.clear(); + return (books != null) ? books.get(0) : null; + } + + @Override + public List getAllObjects() { + List books = em.createQuery("select distinct b " + + "from Book b " + + "inner join fetch b.author a " + + "inner join fetch b.genre g " + + "left join b.comments c " + + "order by b.id ", Book.class) + .getResultList(); + + em.clear(); + return books; + } + + @Override + public int save(Book book) { + if (book.getId() == 0) { + em.persist(book); + } else { + em.merge(book); + } + System.out.println("Book saved with id: " + book.getId()); + return 1; + } + + @Override + public int deleteObject(long id) { + return em.createQuery("delete from Book b where b.id = :id ") + .setParameter("id", id) + .executeUpdate(); + } +} + diff --git a/src/main/java/ru/otus/mkulikov/app/dao/CommentDao.java b/src/main/java/ru/otus/mkulikov/app/dao/CommentDao.java new file mode 100644 index 0000000..49ddac6 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/dao/CommentDao.java @@ -0,0 +1,26 @@ +package ru.otus.mkulikov.app.dao; + +import ru.otus.mkulikov.app.model.Book; +import ru.otus.mkulikov.app.model.Comment; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 20.06.2019 + * Time: 23:48 + */ + +public interface CommentDao { + + T getById(long id); + + List getByBook(Book book); + + int save(T t); + + List getAllObjects(); + + int deleteObject(long id); +} diff --git a/src/main/java/ru/otus/mkulikov/app/dao/CommentDaoJpa.java b/src/main/java/ru/otus/mkulikov/app/dao/CommentDaoJpa.java new file mode 100644 index 0000000..94a313d --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/dao/CommentDaoJpa.java @@ -0,0 +1,80 @@ +package ru.otus.mkulikov.app.dao; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; +import ru.otus.mkulikov.app.model.Book; +import ru.otus.mkulikov.app.model.Comment; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 17:06 + */ + +@SuppressWarnings({"SqlNoDataSourceInspection", "ConstantConditions", "SqlDialectInspection"}) +@Repository +@Transactional +@RequiredArgsConstructor +public class CommentDaoJpa implements CommentDao { + + @PersistenceContext + private EntityManager em; + + @Override + public Comment getById(long id) { + List list = em.createQuery( + "select c " + + "from Comment c " + + "inner join fetch c.book b " + + "where c.id = :id", Comment.class) + .setParameter("id", id) + .getResultList(); + + em.clear(); + return (list != null && !list.isEmpty()) ? list.get(0) : null; + } + + @Override + public List getByBook(Book book) { + List list = em.createQuery( + "select c " + + "from Comment c " + + "inner join fetch c.book b " + + "where c.book = :book", Comment.class) + .setParameter("book", book) + .getResultList(); + + em.clear(); + return list; + } + + @Override + public int save(Comment comment) { + if (comment.getId() == 0) { + em.persist(comment); + } else { + em.merge(comment); + } + System.out.println("Comment saved with id: " + comment.getId()); + return 1; + } + + @Override + public List getAllObjects() { + return em.createQuery("select a from Comment a order by a.id", Comment.class) + .getResultList(); + } + + @Override + public int deleteObject(long id) { + return em.createQuery("delete from Comment a where a.id = :id ") + .setParameter("id", id) + .executeUpdate(); + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/dao/GenreDao.java b/src/main/java/ru/otus/mkulikov/app/dao/GenreDao.java new file mode 100644 index 0000000..4121f3f --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/dao/GenreDao.java @@ -0,0 +1,23 @@ +package ru.otus.mkulikov.app.dao; + +import ru.otus.mkulikov.app.model.Genre; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 17:07 + */ + +public interface GenreDao { + + T getById(long id); + + List getAllObjects(); + + int save(T t); + + int deleteObject(long id); +} diff --git a/src/main/java/ru/otus/mkulikov/app/dao/GenreDaoJpa.java b/src/main/java/ru/otus/mkulikov/app/dao/GenreDaoJpa.java new file mode 100644 index 0000000..f487fd2 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/dao/GenreDaoJpa.java @@ -0,0 +1,70 @@ +package ru.otus.mkulikov.app.dao; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; +import ru.otus.mkulikov.app.model.Genre; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 17:07 + */ + +@SuppressWarnings({"SqlNoDataSourceInspection", "ConstantConditions", "SqlDialectInspection"}) +@Repository +@Transactional +@RequiredArgsConstructor +public class GenreDaoJpa implements GenreDao { + + @PersistenceContext + private EntityManager em; + + @Override + public Genre getById(long id) { + List list = em.createQuery( + "select g " + + "from Genre g " + + "where g.id = :id ", Genre.class) + .setParameter("id", id) + .getResultList(); + + em.clear(); + return (list != null && !list.isEmpty()) ? list.get(0) : null; + } + + @Override + public List getAllObjects() { + List list = em.createQuery( + "select g " + + "from Genre g " + + "order by g.id", Genre.class) + .getResultList(); + + em.clear(); + return list; + } + + @Override + public int save(Genre genre) { + if (genre.getId() == 0) { + em.persist(genre); + } else { + em.merge(genre); + } + System.out.println("Genre saved with id: " + genre.getId()); + return 1; + } + + @Override + public int deleteObject(long id) { + return em.createQuery("delete from Genre g where g.id = :id ") + .setParameter("id", id) + .executeUpdate(); + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/model/Author.java b/src/main/java/ru/otus/mkulikov/app/model/Author.java new file mode 100644 index 0000000..edca570 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/model/Author.java @@ -0,0 +1,57 @@ +package ru.otus.mkulikov.app.model; + +import lombok.Data; + +import javax.persistence.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 17:02 + */ + +@Data +@Entity +@Table(name = "AUTHOR") +public class Author { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sq_author") + @SequenceGenerator(name = "sq_author", sequenceName = "sq_author", allocationSize = 1) + @Column(name = "ID") + private long id; + @Column(name = "SURNAME") + private String surname; + @Column(name = "FIRST_NAME") + private String firstName; + @Column(name = "SECOND_NAME") + private String secondName; + + public Author() { + } + + public Author(long id, String surname, String firstName, String secondName) { + this.id = id; + this.surname = surname; + this.firstName = firstName; + this.secondName = secondName; + } + + public Author(String surname, String firstName, String secondName) { + this.id = 0L; + this.surname = surname; + this.firstName = firstName; + this.secondName = secondName; + } + + @Override + public String toString() { + return "Author{" + + "id=" + id + + ", surname='" + surname + '\'' + + ", firstName='" + firstName + '\'' + + ", secondName='" + secondName + '\'' + + "}\n"; + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/model/Book.java b/src/main/java/ru/otus/mkulikov/app/model/Book.java new file mode 100644 index 0000000..7586ff6 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/model/Book.java @@ -0,0 +1,90 @@ +package ru.otus.mkulikov.app.model; + +import lombok.Data; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; + +import javax.persistence.*; +import java.util.Date; +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 13:28 + */ + +@Data +@Entity +@Table(name = "BOOK") +public class Book { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sq_book") + @SequenceGenerator(name = "sq_book", sequenceName = "sq_book", allocationSize = 1) + @Column(name = "ID") + private long id; + @Column(name = "ADD_RECORD_DATE") + private Date addRecordDate; + @Column(name = "CAPTION") + private String caption; + @Column(name = "DESCRIPTION") + private String description; + + @Fetch(FetchMode.JOIN) + @ManyToOne(optional=false, fetch = FetchType.EAGER) + private Author author; + + @Fetch(FetchMode.JOIN) + @ManyToOne(optional=false, fetch = FetchType.EAGER) + private Genre genre; + + @Fetch(FetchMode.JOIN) + @OneToMany(mappedBy = "book", fetch = FetchType.LAZY) + @OnDelete(action = OnDeleteAction.CASCADE) + private List comments; + + public Book() { + } + + public Book(long id, Date addRecordDate, String caption, Author author, Genre genre, String description) { + this.id = id; + this.addRecordDate = addRecordDate; + this.author = author; + this.genre = genre; + this.caption = caption; + this.description = description; + } + + public Book(long id, String caption, Author author, Genre genre, String description) { + this.id = id; + this.caption = caption; + this.author = author; + this.genre = genre; + this.description = description; + } + + public Book(String caption, Author author, Genre genre, String description) { + this.id = 0L; + this.caption = caption; + this.author = author; + this.genre = genre; + this.description = description; + } + + @Override + public String toString() { + return "Book{" + + "id=" + id + + ", addRecordDate=" + addRecordDate + + ", caption='" + caption + '\'' + + ", description=" + description + + ", author=" + author + + ", genre=" + genre + + ", comments=" + (comments != null ? comments : "none") + + "}\n"; + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/model/Comment.java b/src/main/java/ru/otus/mkulikov/app/model/Comment.java new file mode 100644 index 0000000..dd7a0a5 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/model/Comment.java @@ -0,0 +1,67 @@ +package ru.otus.mkulikov.app.model; + +import lombok.Data; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; + +import javax.persistence.*; +import java.util.Date; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 20.06.2019 + * Time: 23:38 + */ + +@Data +@Entity +@Table(name = "COMMENT") +public class Comment { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sq_comment") + @SequenceGenerator(name = "sq_comment", sequenceName = "sq_comment", allocationSize = 1) + @Column(name = "ID") + private long id; + @Column(name = "ADD_RECORD_DATE") + @Temporal(TemporalType.TIMESTAMP) + private Date addRecordDate; + @Column(name = "USER_NAME") + private String userName; + @Column(name = "TEXT") + private String text; + + @Fetch(FetchMode.JOIN) + @ManyToOne(optional=false, fetch = FetchType.EAGER) + private Book book; + + public Comment() { + } + + public Comment(long id, Book book, Date addRecordDate, String userName, String text) { + this.id = id; + this.book = book; + this.addRecordDate = addRecordDate; + this.userName = userName; + this.text = text; + } + + public Comment(Book book, Date addRecordDate, String userName, String text) { + this.id = 0L; + this.book = book; + this.addRecordDate = addRecordDate; + this.userName = userName; + this.text = text; + } + + @Override + public String toString() { + return "Comment{" + + "id=" + id + + ", addRecordDate=" + addRecordDate + + ", userName=" + userName + + ", text='" + text + '\'' + + "}\n"; + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/model/Genre.java b/src/main/java/ru/otus/mkulikov/app/model/Genre.java new file mode 100644 index 0000000..dc37847 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/model/Genre.java @@ -0,0 +1,47 @@ +package ru.otus.mkulikov.app.model; + +import lombok.Data; + +import javax.persistence.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 17:04 + */ + +@Data +@Entity +@Table(name = "GENRE") +public class Genre { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sq_genre") + @SequenceGenerator(name = "sq_genre", sequenceName = "sq_genre", allocationSize = 1) + @Column(name = "ID") + private long id; + @Column(name = "NAME") + private String name; + + public Genre() { + } + + public Genre(long id, String name) { + this.id = id; + this.name = name; + } + + public Genre(String name) { + this.id = 0L; + this.name = name; + } + + @Override + public String toString() { + return "Genre{" + + "id=" + id + + ", name='" + name + '\'' + + "}\n"; + } +} \ No newline at end of file diff --git a/src/main/java/ru/otus/mkulikov/app/service/AuthorManageService.java b/src/main/java/ru/otus/mkulikov/app/service/AuthorManageService.java new file mode 100644 index 0000000..2ebc5f1 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/service/AuthorManageService.java @@ -0,0 +1,25 @@ +package ru.otus.mkulikov.app.service; + +import ru.otus.mkulikov.app.model.Author; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 14:59 + */ + +public interface AuthorManageService { + + T getAuthorById(long id); + + List getAuthors(); + + int addAuthor(String surname, String firstName, String secondName); + + int updateAuthor(long id, String surname, String firstName, String secondName); + + int deleteAuthor(long id); +} diff --git a/src/main/java/ru/otus/mkulikov/app/service/AuthorManageServiceImpl.java b/src/main/java/ru/otus/mkulikov/app/service/AuthorManageServiceImpl.java new file mode 100644 index 0000000..f0bd226 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/service/AuthorManageServiceImpl.java @@ -0,0 +1,47 @@ +package ru.otus.mkulikov.app.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.otus.mkulikov.app.dao.AuthorDao; +import ru.otus.mkulikov.app.model.Author; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 15:53 + */ + +@Service +@RequiredArgsConstructor +public class AuthorManageServiceImpl implements AuthorManageService { + + private final AuthorDao authorDao; + + @Override + public Author getAuthorById(long id) { + return authorDao.getById(id); + } + + @Override + public List getAuthors() { + return authorDao.getAllObjects(); + } + + @Override + public int addAuthor(String surname, String firstName, String secondName) { + return authorDao.save(new Author(surname, firstName, secondName)); + } + + @Override + public int updateAuthor(long id, String surname, String firstName, String secondName) { + return authorDao.save(new Author(id, surname, firstName, secondName)); + } + + @Override + public int deleteAuthor(long id) { + return authorDao.deleteObject(id); + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/service/BookManageSevice.java b/src/main/java/ru/otus/mkulikov/app/service/BookManageSevice.java new file mode 100644 index 0000000..e08867d --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/service/BookManageSevice.java @@ -0,0 +1,25 @@ +package ru.otus.mkulikov.app.service; + +import ru.otus.mkulikov.app.model.Book; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 27.05.2019 + * Time: 13:42 + */ + +public interface BookManageSevice { + + T getBookById(long id); + + List getBooks(); + + int addBook(String caption, int authorId, int genreId, String description); + + int updateBook(long id, String caption, int authorId, int genreId, String description); + + int deleteBook(long id); +} diff --git a/src/main/java/ru/otus/mkulikov/app/service/BookManageSeviceImpl.java b/src/main/java/ru/otus/mkulikov/app/service/BookManageSeviceImpl.java new file mode 100644 index 0000000..94a97f1 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/service/BookManageSeviceImpl.java @@ -0,0 +1,59 @@ +package ru.otus.mkulikov.app.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.otus.mkulikov.app.dao.AuthorDao; +import ru.otus.mkulikov.app.dao.BookDao; +import ru.otus.mkulikov.app.dao.GenreDao; +import ru.otus.mkulikov.app.model.Author; +import ru.otus.mkulikov.app.model.Book; +import ru.otus.mkulikov.app.model.Genre; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 27.05.2019 + * Time: 13:42 + */ + +@Service +@RequiredArgsConstructor +public class BookManageSeviceImpl implements BookManageSevice { + + private final BookDao bookDao; + private final AuthorDao authorDao; + private final GenreDao genreDao; + + @Override + public Book getBookById(long id) { + return bookDao.getById(id); + } + + @Override + public List getBooks() { + return bookDao.getAllObjects(); + } + + @Override + public int addBook(String caption, int authorId, int genreId, String description) { + Author author = authorDao.getById(authorId); + Genre genre = genreDao.getById(genreId); + + return bookDao.save(new Book(caption, author, genre, description)); + } + + @Override + public int updateBook(long id, String caption, int authorId, int genreId, String description) { + Author author = authorDao.getById(authorId); + Genre genre = genreDao.getById(genreId); + + return bookDao.save(new Book(id, caption, author, genre, description)); + } + + @Override + public int deleteBook(long id) { + return bookDao.deleteObject(id); + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/service/CommentManageService.java b/src/main/java/ru/otus/mkulikov/app/service/CommentManageService.java new file mode 100644 index 0000000..5c9e5e7 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/service/CommentManageService.java @@ -0,0 +1,26 @@ +package ru.otus.mkulikov.app.service; + +import ru.otus.mkulikov.app.model.Comment; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 15:50 + */ +public interface CommentManageService { + + T getCommentById(long id); + + List getComments(); + + List getCommentsByBookId(long bookId); + + int addComment(long bookId, String userName, String text); + + int updateComment(long id, String userName, String text); + + int deleteComment(long id); +} diff --git a/src/main/java/ru/otus/mkulikov/app/service/CommentManageServiceImpl.java b/src/main/java/ru/otus/mkulikov/app/service/CommentManageServiceImpl.java new file mode 100644 index 0000000..591e132 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/service/CommentManageServiceImpl.java @@ -0,0 +1,65 @@ +package ru.otus.mkulikov.app.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.otus.mkulikov.app.dao.BookDao; +import ru.otus.mkulikov.app.dao.CommentDao; +import ru.otus.mkulikov.app.model.Book; +import ru.otus.mkulikov.app.model.Comment; + +import java.util.Date; +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 15:52 + */ + +@Service +@RequiredArgsConstructor +public class CommentManageServiceImpl implements CommentManageService { + + private final CommentDao commentDao; + private final BookDao bookDao; + + @Override + public Comment getCommentById(long id) { + return commentDao.getById(id); + } + + @Override + public List getComments() { + return commentDao.getAllObjects(); + } + + @Override + public List getCommentsByBookId(long bookId) { + Book book = bookDao.getById(bookId); + + return commentDao.getByBook(book); + } + + @Override + public int addComment(long bookId, String userName, String text) { + Book book = bookDao.getById(bookId); + + return commentDao.save(new Comment(book, new Date(), userName, text)); + } + + @Override + public int updateComment(long id, String userName, String text) { + Comment comment = commentDao.getById(id); + comment.setAddRecordDate(new Date()); + comment.setUserName(userName); + comment.setText(text); + + return commentDao.save(comment); + } + + @Override + public int deleteComment(long id) { + return commentDao.deleteObject(id); + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/service/GenreManageService.java b/src/main/java/ru/otus/mkulikov/app/service/GenreManageService.java new file mode 100644 index 0000000..80015b3 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/service/GenreManageService.java @@ -0,0 +1,24 @@ +package ru.otus.mkulikov.app.service; + +import ru.otus.mkulikov.app.model.Genre; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 15:50 + */ +public interface GenreManageService { + + T getGenreById(long id); + + List getGenres(); + + int addGenre(String name); + + int updateGenre(long id, String name); + + int deleteGenre(long id); +} diff --git a/src/main/java/ru/otus/mkulikov/app/service/GenreManageServiceImpl.java b/src/main/java/ru/otus/mkulikov/app/service/GenreManageServiceImpl.java new file mode 100644 index 0000000..2cf897a --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/service/GenreManageServiceImpl.java @@ -0,0 +1,47 @@ +package ru.otus.mkulikov.app.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.otus.mkulikov.app.dao.GenreDao; +import ru.otus.mkulikov.app.model.Genre; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 15:52 + */ + +@Service +@RequiredArgsConstructor +public class GenreManageServiceImpl implements GenreManageService { + + private final GenreDao genreDao; + + @Override + public Genre getGenreById(long id) { + return genreDao.getById(id); + } + + @Override + public List getGenres() { + return genreDao.getAllObjects(); + } + + @Override + public int addGenre(String name) { + return genreDao.save(new Genre(name)); + } + + @Override + public int updateGenre(long id, String name) { + return genreDao.save(new Genre(id, name)); + } + + @Override + public int deleteGenre(long id) { + return genreDao.deleteObject(id); + } +} diff --git a/src/main/java/ru/otus/mkulikov/app/utils/DateUtil.java b/src/main/java/ru/otus/mkulikov/app/utils/DateUtil.java new file mode 100644 index 0000000..ffbce20 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/app/utils/DateUtil.java @@ -0,0 +1,29 @@ +package ru.otus.mkulikov.app.utils; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 05.06.2019 + * Time: 11:33 + */ + +public class DateUtil { + + private final static String DATE_FORMAT = "yyyy-MM-dd"; + + private final static String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + public static String dateToString(Date date) { + DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); + return date != null ? dateFormat.format(date) : null; + } + + public static String dateTimeToString(Date date) { + DateFormat dateFormat = new SimpleDateFormat(DATE_TIME_FORMAT); + return date != null ? dateFormat.format(date) : null; + } +} diff --git a/src/main/java/ru/otus/mkulikov/shell/AuthorCommands.java b/src/main/java/ru/otus/mkulikov/shell/AuthorCommands.java new file mode 100644 index 0000000..2ace11e --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/shell/AuthorCommands.java @@ -0,0 +1,54 @@ +package ru.otus.mkulikov.shell; + +import lombok.RequiredArgsConstructor; +import org.springframework.shell.standard.ShellComponent; +import org.springframework.shell.standard.ShellMethod; +import org.springframework.shell.standard.ShellOption; +import ru.otus.mkulikov.app.model.Author; +import ru.otus.mkulikov.app.service.AuthorManageService; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 14:46 + */ + +@ShellComponent +@RequiredArgsConstructor +public class AuthorCommands { + + private final AuthorManageService authorManageService; + + @ShellMethod(key = {"getAuthorById"}, value = "Select author by id.") + public String getAuthorById(@ShellOption long id) { + Author author = authorManageService.getAuthorById(id); + return author.toString(); + } + + @ShellMethod(key = {"getAuthors"}, value = "Select all authors.") + public String getAuthors() { + List allObjects = authorManageService.getAuthors(); + return allObjects.toString(); + } + + @ShellMethod(key = {"addAuthor"}, value = "Add new author.") + public String addAuthor(@ShellOption String surname, @ShellOption String firstName, @ShellOption String secondName) { + int count = authorManageService.addAuthor(surname, firstName, secondName); + return "Add " + count + " row(s)"; + } + + @ShellMethod(key = {"updateAuthor"}, value = "Update author by id.") + public String updateAuthor(@ShellOption long id, @ShellOption String surname, @ShellOption String firstName, @ShellOption String secondName) { + int count = authorManageService.updateAuthor(id, surname, firstName, secondName); + return "Updated " + count + " row(s)"; + } + + @ShellMethod(key = {"deleteAuthor"}, value = "Delete author by id.") + public String deleteAuthor(@ShellOption long id) { + int count = authorManageService.deleteAuthor(id); + return "Deleted " + count + " row(s)"; + } +} diff --git a/src/main/java/ru/otus/mkulikov/shell/BookCommands.java b/src/main/java/ru/otus/mkulikov/shell/BookCommands.java new file mode 100644 index 0000000..b5119f5 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/shell/BookCommands.java @@ -0,0 +1,54 @@ +package ru.otus.mkulikov.shell; + +import lombok.RequiredArgsConstructor; +import org.springframework.shell.standard.ShellComponent; +import org.springframework.shell.standard.ShellMethod; +import org.springframework.shell.standard.ShellOption; +import ru.otus.mkulikov.app.model.Book; +import ru.otus.mkulikov.app.service.BookManageSevice; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 23.05.2019 + * Time: 17:33 + */ + +@ShellComponent +@RequiredArgsConstructor +public class BookCommands { + + private final BookManageSevice bookManageSevice; + + @ShellMethod(key = {"getBookById"}, value = "Select book by id.") + public String getBookById(@ShellOption long id) { + Book book = bookManageSevice.getBookById(id); + return book.toString(); + } + + @ShellMethod(key = {"getBooks"}, value = "Select all books.") + public String getBooks() { + List allObjects = bookManageSevice.getBooks(); + return allObjects.toString(); + } + + @ShellMethod(key = {"addBook"}, value = "Add new book.") + public String addBook(@ShellOption String caption, @ShellOption int authorId, @ShellOption int genreId, @ShellOption String description) { + int count = bookManageSevice.addBook(caption, authorId, genreId, description); + return "Add " + count + " row(s)"; + } + + @ShellMethod(key = {"updateBook"}, value = "Update book by id.") + public String updateBook(@ShellOption long id, @ShellOption String caption, @ShellOption int authorId, @ShellOption int genreId, @ShellOption String description) { + int count = bookManageSevice.updateBook(id, caption, authorId, genreId, description); + return "Updated " + count + " row(s)"; + } + + @ShellMethod(key = {"deleteBook"}, value = "Delete book by id.") + public String deleteBook(@ShellOption long id) { + int count = bookManageSevice.deleteBook(id); + return "Deleted " + count + " row(s)"; + } +} diff --git a/src/main/java/ru/otus/mkulikov/shell/CommentCommands.java b/src/main/java/ru/otus/mkulikov/shell/CommentCommands.java new file mode 100644 index 0000000..3965c34 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/shell/CommentCommands.java @@ -0,0 +1,60 @@ +package ru.otus.mkulikov.shell; + +import lombok.RequiredArgsConstructor; +import org.springframework.shell.standard.ShellComponent; +import org.springframework.shell.standard.ShellMethod; +import org.springframework.shell.standard.ShellOption; +import ru.otus.mkulikov.app.model.Comment; +import ru.otus.mkulikov.app.service.CommentManageService; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 14:47 + */ + +@ShellComponent +@RequiredArgsConstructor +public class CommentCommands { + + private final CommentManageService commentManageService; + + @ShellMethod(key = {"getCommentById"}, value = "Select comment by id.") + public String getCommentById(@ShellOption long id) { + Comment comment = commentManageService.getCommentById(id); + return comment.toString(); + } + + @ShellMethod(key = {"getComments"}, value = "Select all comments.") + public String getComments() { + List allObjects = commentManageService.getComments(); + return allObjects.toString(); + } + + @ShellMethod(key = {"getCommentsByBookId"}, value = "Select all comments.") + public String getCommentsByBookId(@ShellOption long bookId) { + List allObjects = commentManageService.getCommentsByBookId(bookId); + return allObjects.toString(); + } + + @ShellMethod(key = {"addComment"}, value = "Add new comment.") + public String addComment(@ShellOption long bookId, @ShellOption String userName, @ShellOption String text) { + int count = commentManageService.addComment(bookId, userName, text); + return "Add " + count + " row(s)"; + } + + @ShellMethod(key = {"updateComment"}, value = "Update comment by id.") + public String updateComment(@ShellOption long id, @ShellOption String userName, @ShellOption String text) { + int count = commentManageService.updateComment(id, userName, text); + return "Updated " + count + " row(s)"; + } + + @ShellMethod(key = {"deleteComment"}, value = "Delete comment by id.") + public String deleteComment(@ShellOption long id) { + int count = commentManageService.deleteComment(id); + return "Deleted " + count + " row(s)"; + } +} diff --git a/src/main/java/ru/otus/mkulikov/shell/GenreCommands.java b/src/main/java/ru/otus/mkulikov/shell/GenreCommands.java new file mode 100644 index 0000000..eb2344e --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/shell/GenreCommands.java @@ -0,0 +1,54 @@ +package ru.otus.mkulikov.shell; + +import lombok.RequiredArgsConstructor; +import org.springframework.shell.standard.ShellComponent; +import org.springframework.shell.standard.ShellMethod; +import org.springframework.shell.standard.ShellOption; +import ru.otus.mkulikov.app.model.Genre; +import ru.otus.mkulikov.app.service.GenreManageService; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 14:47 + */ + +@ShellComponent +@RequiredArgsConstructor +public class GenreCommands { + + private final GenreManageService genreManageService; + + @ShellMethod(key = {"getGenreById"}, value = "Select genre by id.") + public String getGenreById(@ShellOption long id) { + Genre genre = genreManageService.getGenreById(id); + return genre.toString(); + } + + @ShellMethod(key = {"getGenres"}, value = "Select all genres.") + public String getGenres() { + List allObjects = genreManageService.getGenres(); + return allObjects.toString(); + } + + @ShellMethod(key = {"addGenre"}, value = "Add new genre.") + public String addGenre(@ShellOption String name) { + int count = genreManageService.addGenre(name); + return "Add " + count + " row(s)"; + } + + @ShellMethod(key = {"updateGenre"}, value = "Update genre by id.") + public String updateGenre(@ShellOption long id, @ShellOption String name) { + int count = genreManageService.updateGenre(id, name); + return "Updated " + count + " row(s)"; + } + + @ShellMethod(key = {"deleteGenre"}, value = "Delete genre by id.") + public String deleteGenre(@ShellOption long id) { + int count = genreManageService.deleteGenre(id); + return "Deleted " + count + " row(s)"; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..91ca387 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,16 @@ +spring: + banner: + location: "classpath:banner.txt" + + datasource: + initialization-mode: always + platform: h2 + + jpa: + hibernate: + ddl-auto: none + + properties: + hibernate: + show_sql: false + format_sql: false diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000..1687640 --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,11 @@ + ___ ___ ___ ___ ___ + /\__\ /\ \ /\__\ /\ \ /\ \ + /:/ / /::\ \ /:/ / /::\ \ /::\ \ + /:/ / /:/\:\ \ /:/ / /:/\:\ \ /:/\ \ \ + /:/ / ___ /:/ \:\ \ /:/ / /::\~\:\ \ _\:\~\ \ \ + /:/__/ /\__\ /:/__/ \:\__\ /:/__/ /:/\:\ \:\__\ /\ \:\ \ \__\ + \:\ \ /:/ / \:\ \ /:/ / \:\ \ \:\~\:\ \/__/ \:\ \:\ \/__/ + \:\ /:/ / \:\ /:/ / \:\ \ \:\ \:\__\ \:\ \:\__\ + \:\/:/ / \:\/:/ / \:\ \ \:\ \/__/ \:\/:/ / + \::/ / \::/ / \:\__\ \:\__\ \::/ / + \/__/ \/__/ \/__/ \/__/ \/__/ \ No newline at end of file diff --git a/src/main/resources/data-h2.sql b/src/main/resources/data-h2.sql new file mode 100644 index 0000000..bca97c4 --- /dev/null +++ b/src/main/resources/data-h2.sql @@ -0,0 +1,39 @@ +insert into AUTHOR (ID, SURNAME, FIRST_NAME, SECOND_NAME) +values (sq_author.nextval, 'Surname1', 'FirstName1', 'SecondName1'); + +insert into AUTHOR (ID, SURNAME, FIRST_NAME, SECOND_NAME) +values (sq_author.nextval, 'Surname2', 'FirstName2', 'SecondName2'); + +insert into AUTHOR (ID, SURNAME, FIRST_NAME, SECOND_NAME) +values (sq_author.nextval, 'Surname3', 'FirstName3', 'SecondName3'); + +-------------------------- + +insert into GENRE (ID, NAME) values (sq_genre.nextval, 'Genre1'); +insert into GENRE (ID, NAME) values (sq_genre.nextval, 'Genre2'); +insert into GENRE (ID, NAME) values (sq_genre.nextval, 'Genre3'); + +-------------------------- + +insert into BOOK (ID, ADD_RECORD_DATE, CAPTION, AUTHOR_ID, GENRE_ID, DESCRIPTION) +values (sq_book.nextval, to_date('2019-01-01','YYYY-MM-DD'), 'book_1', 1, 1, 'description'); + +insert into BOOK (ID, ADD_RECORD_DATE, CAPTION, AUTHOR_ID, GENRE_ID, DESCRIPTION) +values (sq_book.nextval, to_date('2019-01-01','YYYY-MM-DD'), 'book_2', 1, 1, 'description'); + +insert into BOOK (ID, ADD_RECORD_DATE, CAPTION, AUTHOR_ID, GENRE_ID, DESCRIPTION) +values (sq_book.nextval, to_date('2019-01-01','YYYY-MM-DD'), 'book_3', 1, 1, 'description'); + +-------------------------- + +insert into COMMENT (ID, BOOK_ID, ADD_RECORD_DATE, USER_NAME, TEXT) +values (sq_comment.nextval, 1, to_date('2019-01-01 10:01:01','YYYY-MM-DD HH24-MI-SS'), 'user1', 'text1'); + +insert into COMMENT (ID, BOOK_ID, ADD_RECORD_DATE, USER_NAME, TEXT) +values (sq_comment.nextval, 1, to_date('2019-01-01 10:01:02','YYYY-MM-DD HH24-MI-SS'), 'user2', 'text2'); + +insert into COMMENT (ID, BOOK_ID, ADD_RECORD_DATE, USER_NAME, TEXT) +values (sq_comment.nextval, 2, to_date('2019-01-01 10:01:03','YYYY-MM-DD HH24-MI-SS'), 'user3', 'text3'); + +insert into COMMENT (ID, BOOK_ID, ADD_RECORD_DATE, USER_NAME, TEXT) +values (sq_comment.nextval, 2, to_date('2019-01-01 10:01:04','YYYY-MM-DD HH24-MI-SS'), 'user4', 'text4'); \ No newline at end of file diff --git a/src/main/resources/schema-h2.sql b/src/main/resources/schema-h2.sql new file mode 100644 index 0000000..7156478 --- /dev/null +++ b/src/main/resources/schema-h2.sql @@ -0,0 +1,43 @@ +DROP TABLE IF EXISTS BOOK; +DROP TABLE IF EXISTS AUTHOR; +DROP TABLE IF EXISTS GENRE; +DROP TABLE IF EXISTS COMMENT; + +CREATE TABLE AUTHOR( + ID NUMBER(20,0) PRIMARY KEY not null, + SURNAME VARCHAR(100) not null, + FIRST_NAME VARCHAR(100) not null, + SECOND_NAME VARCHAR(100) +); + +CREATE TABLE GENRE( + ID NUMBER(20,0) PRIMARY KEY not null, + NAME VARCHAR(100) not null +); + +CREATE TABLE BOOK( + ID NUMBER(20,0) PRIMARY KEY not null, + ADD_RECORD_DATE DATE default sysdate, + CAPTION VARCHAR(255) not null, + AUTHOR_ID NUMBER(20,0) not null, + GENRE_ID NUMBER(20,0) not null, + DESCRIPTION VARCHAR(255), + + foreign key (AUTHOR_ID) references AUTHOR(ID), + foreign key (GENRE_ID) references GENRE(ID) +); + +CREATE TABLE COMMENT( + ID NUMBER(20,0) PRIMARY KEY not null, + BOOK_ID NUMBER(20,0) not null, + ADD_RECORD_DATE TIMESTAMP default sysdate, + USER_NAME VARCHAR(20), + TEXT VARCHAR(500), + + foreign key (BOOK_ID) references BOOK(ID) ON DELETE CASCADE +); + +CREATE SEQUENCE sq_author minvalue 1 start with 1 increment by 1; +CREATE SEQUENCE sq_genre minvalue 1 start with 1 increment by 1; +CREATE SEQUENCE sq_book minvalue 1 start with 1 increment by 1; +CREATE SEQUENCE sq_comment minvalue 1 start with 1 increment by 1; \ No newline at end of file diff --git a/src/test/java/ru/otus/mkulikov/app/dao/AuthorDaoJpaTest.java b/src/test/java/ru/otus/mkulikov/app/dao/AuthorDaoJpaTest.java new file mode 100644 index 0000000..3ec510f --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/app/dao/AuthorDaoJpaTest.java @@ -0,0 +1,109 @@ +package ru.otus.mkulikov.app.dao; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import ru.otus.mkulikov.app.model.Author; + +import javax.persistence.PersistenceException; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 29.05.2019 + * Time: 10:12 + */ + +@DisplayName("Класс AuthorDaoJpa") +@RunWith(SpringRunner.class) +@Import(AuthorDaoJpa.class) +@DataJpaTest +@TestPropertySource(locations= "classpath:application.yml") +class AuthorDaoJpaTest { + + @Autowired + private AuthorDao authorDaoJpa; + + @Test + @DisplayName("Получение автора по id") + void getById() { + Author author = authorDaoJpa.getById(1L); + + assertAll( + "author", + () -> assertNotNull(author), + () -> assertEquals(1L, author.getId()), + () -> assertEquals("Surname", author.getSurname()), + () -> assertEquals("FirstName", author.getFirstName()), + () -> assertEquals("SecondName", author.getSecondName()) + ); + } + + @Test + @DisplayName("Получение всех авторов") + void getAllObjects() { + List authors = authorDaoJpa.getAllObjects(); + + assertAll( + "authors", + () -> assertNotNull(authors), + () -> assertEquals(3, authors.size()), + () -> assertEquals("Surname", authors.get(0).getSurname()), + () -> assertEquals("Surname2", authors.get(1).getSurname()), + () -> assertEquals("Surname3", authors.get(2).getSurname()) + ); + } + + @Test + @DisplayName("Добавление автора") + void addObject() { + Author author = new Author("TestSurname", "TestFirstName", "TestSecondName"); + int count = authorDaoJpa.save(author); + Author author_selected = authorDaoJpa.getById(4L); + + assertAll( + "author", + () -> assertNotNull(author_selected), + () -> assertEquals(1, count), + () -> assertEquals(4, author_selected.getId()), + () -> assertEquals(author.getSurname(), author_selected.getSurname()), + () -> assertEquals(author.getFirstName(), author_selected.getFirstName()), + () -> assertEquals(author.getSecondName(), author_selected.getSecondName()) + ); + } + + @Test + @DisplayName("Удаление автора, который используется в таблице книг") + void deleteObject() { + assertThrows(PersistenceException.class, () -> { authorDaoJpa.deleteObject(1L); }); + } + + @Test + @DisplayName("Обновление автора") + void updateObject() { + Author author1 = authorDaoJpa.getById(1L); + int count = authorDaoJpa.save( + new Author(1L, "TestSurname", "TestFirstName", "TestSecondName") + ); + Author author2 = authorDaoJpa.getById(1L); + + assertAll( + "author", + () -> assertEquals(1, count), + () -> assertEquals("Surname", author1.getSurname()), + () -> assertEquals("FirstName", author1.getFirstName()), + () -> assertEquals("SecondName", author1.getSecondName()), + () -> assertEquals("TestSurname", author2.getSurname()), + () -> assertEquals("TestFirstName", author2.getFirstName()), + () -> assertEquals("TestSecondName", author2.getSecondName()) + ); + } +} \ No newline at end of file diff --git a/src/test/java/ru/otus/mkulikov/app/dao/BookDaoJpaTest.java b/src/test/java/ru/otus/mkulikov/app/dao/BookDaoJpaTest.java new file mode 100644 index 0000000..6c1e247 --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/app/dao/BookDaoJpaTest.java @@ -0,0 +1,131 @@ +package ru.otus.mkulikov.app.dao; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import ru.otus.mkulikov.app.model.Author; +import ru.otus.mkulikov.app.model.Book; +import ru.otus.mkulikov.app.model.Genre; +import ru.otus.mkulikov.app.utils.DateUtil; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 28.05.2019 + * Time: 13:16 + */ + +@DisplayName("Класс BookDaoJpa") +@RunWith(SpringRunner.class) +@Import({BookDaoJpa.class, AuthorDaoJpa.class, GenreDaoJpa.class}) +@DataJpaTest +@TestPropertySource(locations= "classpath:application.yml") +class BookDaoJpaTest { + + @Autowired + private BookDao bookDaoJpa; + @Autowired + private AuthorDao authorDao; + @Autowired + private GenreDao genreDao; + + @Test + @DisplayName("Получение книги по id") + void getById() { + Book book = bookDaoJpa.getById(1L); + + assertAll( + "book", + () -> assertNotNull(book), + () -> assertEquals(1L, book.getId()), + () -> assertEquals("2019-01-01", DateUtil.dateToString(book.getAddRecordDate())), + () -> assertEquals("book_1", book.getCaption()), + () -> assertEquals(1, book.getAuthor().getId()), + () -> assertEquals(1, book.getGenre().getId()), + () -> assertEquals("description", book.getDescription()) + ); + } + + @Test + @DisplayName("Получение всех книг") + void getAllObjects() { + List books = bookDaoJpa.getAllObjects(); + + assertAll( + "books", + () -> assertNotNull(books), + () -> assertEquals(3, books.size()), + () -> assertEquals("book_1", books.get(0).getCaption()), + () -> assertEquals("book_2", books.get(1).getCaption()), + () -> assertEquals("book_3", books.get(2).getCaption()) + ); + } + + @Test + @DisplayName("Добавление книги") + void addObject() { + int count = bookDaoJpa.save(getNewBook()); + Book book = bookDaoJpa.getById(4L); + + assertAll( + "book", + () -> assertNotNull(book), + () -> assertEquals(1, count), + () -> assertEquals(4L, book.getId()), + () -> assertEquals("Test_Book", book.getCaption()), + () -> assertEquals(1, book.getAuthor().getId()), + () -> assertEquals(1, book.getGenre().getId()), + () -> assertEquals("Test_Description", book.getDescription()) + ); + } + + @Test + @DisplayName("Удаление книги по id") + void deleteObject() { + int count = bookDaoJpa.deleteObject(1L); + + assertAll( + "book", + () -> assertEquals(1, count), + () -> assertThrows(IndexOutOfBoundsException.class, () -> { bookDaoJpa.getById(1L); }) + ); + } + + @Test + @DisplayName("Обновление книги") + void updateObject() { + Book book1 = bookDaoJpa.getById(1L); + int count = bookDaoJpa.save(getUpdatedBook()); + Book book2 = bookDaoJpa.getById(1L); + + assertAll( + "book", + () -> assertEquals(1, count), + () -> assertEquals("book_1", book1.getCaption()), + () -> assertEquals("description", book1.getDescription()), + () -> assertEquals("Test_Book", book2.getCaption()), + () -> assertEquals("Test_Description", book2.getDescription()) + ); + } + + private Book getNewBook() { + Author author = authorDao.getById(1); + Genre genre = genreDao.getById(1); + return new Book("Test_Book", author, genre, "Test_Description"); + } + + private Book getUpdatedBook() { + Author author = authorDao.getById(1); + Genre genre = genreDao.getById(1); + return new Book(1L,"Test_Book", author, genre, "Test_Description"); + } +} \ No newline at end of file diff --git a/src/test/java/ru/otus/mkulikov/app/dao/CommentDaoJpaTest.java b/src/test/java/ru/otus/mkulikov/app/dao/CommentDaoJpaTest.java new file mode 100644 index 0000000..3336556 --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/app/dao/CommentDaoJpaTest.java @@ -0,0 +1,139 @@ +package ru.otus.mkulikov.app.dao; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import ru.otus.mkulikov.app.model.Book; +import ru.otus.mkulikov.app.model.Comment; +import ru.otus.mkulikov.app.utils.DateUtil; + +import java.util.Date; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 28.05.2019 + * Time: 9:45 + */ + +@DisplayName("Класс CommentDaoJpa") +@RunWith(SpringRunner.class) +@Import({CommentDaoJpa.class, BookDaoJpa.class}) +@DataJpaTest +@TestPropertySource(locations= "classpath:application.yml") +class CommentDaoJpaTest { + + @Autowired + private BookDao bookDaoJpa; + @Autowired + private CommentDao commentDaoJpa; + + @Test + @DisplayName("Получение комментария по id") + void getById() { + Comment comment = commentDaoJpa.getById(1L); + + assertAll( + "comment", + () -> assertNotNull(comment), + () -> assertNotNull(comment.getBook()), + () -> assertEquals(1L, comment.getId()), + () -> assertEquals("user1", comment.getUserName()), + () -> assertEquals("2019-01-01 10:01:01", DateUtil.dateTimeToString(comment.getAddRecordDate())), + () -> assertEquals("text1", comment.getText()) + ); + } + + @Test + @DisplayName("Получение всех комментариев") + void getAllObjects() { + List comments = commentDaoJpa.getAllObjects(); + + assertAll( + "comments", + () -> assertNotNull(comments), + () -> assertEquals(4, comments.size()), + () -> assertEquals("text1", comments.get(0).getText()), + () -> assertEquals("text2", comments.get(1).getText()), + () -> assertEquals("text3", comments.get(2).getText()), + () -> assertEquals("text4", comments.get(3).getText()) + ); + } + + @Test + @DisplayName("Получение всех комментариев для книги") + void getObjectsByBook() { + Book book = bookDaoJpa.getById(1L); + List comments = commentDaoJpa.getByBook(book); + + assertAll( + "comments", + () -> assertNotNull(comments), + () -> assertEquals(2, comments.size()), + () -> assertEquals("text1", comments.get(0).getText()), + () -> assertEquals("text2", comments.get(1).getText()) + ); + } + + @Test + @DisplayName("Добавление комментария") + void addObject() { + Date date = new Date(); + Book book = bookDaoJpa.getById(1L); + int count = commentDaoJpa.save(new Comment(book, date, "user5", "text5")); + + Comment comment = commentDaoJpa.getById(5L); + + assertAll( + "comment", + () -> assertNotNull(comment), + () -> assertNotNull(comment.getBook()), + () -> assertEquals(1, count), + () -> assertEquals(5L, comment.getId()), + () -> assertEquals(date, comment.getAddRecordDate()), + () -> assertEquals("user5", comment.getUserName()), + () -> assertEquals("text5", comment.getText()) + ); + } + + @Test + @DisplayName("Удаление комментария") + void deleteObject() { + commentDaoJpa.deleteObject(1L); + assertNull(commentDaoJpa.getById(1L)); + } + + @Test + @DisplayName("Обновление комментария") + void updateObject() { + Comment comment1 = commentDaoJpa.getById(1L); + + Date date = new Date(); + int count = commentDaoJpa.save(new Comment(1L, comment1.getBook(), date, "TestUser", "TestText")); + + Comment comment2 = commentDaoJpa.getById(1L); + + assertAll( + "comment", + () -> assertNotNull(comment1), + () -> assertNotNull(comment2), + () -> assertNotNull(comment1.getBook()), + () -> assertNotNull(comment2.getBook()), + () -> assertEquals(1, count), + () -> assertEquals("user1", comment1.getUserName()), + () -> assertEquals("text1", comment1.getText()), + () -> assertEquals(date, comment2.getAddRecordDate()), + () -> assertEquals("TestUser", comment2.getUserName()), + () -> assertEquals("TestText", comment2.getText()) + ); + } + +} \ No newline at end of file diff --git a/src/test/java/ru/otus/mkulikov/app/dao/GenreDaoJpaTest.java b/src/test/java/ru/otus/mkulikov/app/dao/GenreDaoJpaTest.java new file mode 100644 index 0000000..a91800e --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/app/dao/GenreDaoJpaTest.java @@ -0,0 +1,99 @@ +package ru.otus.mkulikov.app.dao; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import ru.otus.mkulikov.app.model.Genre; + +import javax.persistence.PersistenceException; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 28.05.2019 + * Time: 9:45 + */ + +@DisplayName("Класс GenreDaoJpa") +@RunWith(SpringRunner.class) +@Import(GenreDaoJpa.class) +@DataJpaTest +@TestPropertySource(locations= "classpath:application.yml") +class GenreDaoJpaTest { + + @Autowired + private GenreDao genreDaoJpa; + + @Test + @DisplayName("Получение жанра по id") + void getById() { + Genre genre = genreDaoJpa.getById(1L); + + assertAll( + "genre", + () -> assertNotNull(genre), + () -> assertEquals(1L, genre.getId()), + () -> assertEquals("Genre1", genre.getName()) + ); + } + + @Test + @DisplayName("Получение всех жанров") + void getAllObjects() { + List genres = genreDaoJpa.getAllObjects(); + + assertAll( + "genres", + () -> assertNotNull(genres), + () -> assertEquals(3, genres.size()), + () -> assertEquals("Genre1", genres.get(0).getName()), + () -> assertEquals("Genre2", genres.get(1).getName()), + () -> assertEquals("Genre3", genres.get(2).getName()) + ); + } + + @Test + @DisplayName("Добавление жанра") + void addObject() { + int count = genreDaoJpa.save(new Genre("Test4")); + + Genre genre = genreDaoJpa.getById(4L); + + assertAll( + "genre", + () -> assertNotNull(genre), + () -> assertEquals(1, count), + () -> assertEquals(4L, genre.getId()), + () -> assertEquals("Test4", genre.getName()) + ); + } + + @Test + @DisplayName("Удаление жанра, который используется в таблице книг") + void deleteObject() { + assertThrows(PersistenceException.class, () -> { genreDaoJpa.deleteObject(1L); }); + } + + @Test + @DisplayName("Обновление жанра") + void updateObject() { + Genre genre1 = genreDaoJpa.getById(1L); + int count = genreDaoJpa.save(new Genre(1L, "UpdatedName")); + Genre genre2 = genreDaoJpa.getById(1L); + + assertAll( + "genre", + () -> assertEquals(1, count), + () -> assertEquals("Genre1", genre1.getName()), + () -> assertEquals("UpdatedName", genre2.getName()) + ); + } +} \ No newline at end of file diff --git a/src/test/java/ru/otus/mkulikov/app/model/DateUtilTest.java b/src/test/java/ru/otus/mkulikov/app/model/DateUtilTest.java new file mode 100644 index 0000000..1276d90 --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/app/model/DateUtilTest.java @@ -0,0 +1,57 @@ +package ru.otus.mkulikov.app.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.junit4.SpringRunner; +import ru.otus.mkulikov.app.utils.DateUtil; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 29.05.2019 + * Time: 11:39 + */ + +@DisplayName("Класс DateUtil") +@RunWith(SpringRunner.class) +class DateUtilTest { + + @Test + @DisplayName("Формат даты 'yyyy-MM-dd'") + void dateToString() { + Book book = getNewBook(); + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + assertAll( + "book", + () -> assertNotNull(book), + () -> assertEquals(dateFormat.format(new Date()), DateUtil.dateToString(book.getAddRecordDate())) + ); + } + + @Test + @DisplayName("Формат даты 'yyyy-MM-dd HH:mm:ss'") + void dateTimeToString() { + Book book = getNewBook(); + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + assertAll( + "book", + () -> assertNotNull(book), + () -> assertEquals(dateFormat.format(new Date()), DateUtil.dateTimeToString(book.getAddRecordDate())) + ); + } + + private Book getNewBook() { + Author author = new Author(1L, "TestSurname", "TestFirstName", "TestSecondName"); + Genre genre = new Genre("Test4"); + return new Book(1L, new Date(), "Test_Book", author, genre, "Test_Comment"); + } +} \ No newline at end of file diff --git a/src/test/java/ru/otus/mkulikov/app/service/AuthorManageSeviceImplTest.java b/src/test/java/ru/otus/mkulikov/app/service/AuthorManageSeviceImplTest.java new file mode 100644 index 0000000..2203f8c --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/app/service/AuthorManageSeviceImplTest.java @@ -0,0 +1,106 @@ +package ru.otus.mkulikov.app.service; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import ru.otus.mkulikov.app.model.Author; + +import javax.persistence.PersistenceException; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 15:59 + */ + +@DisplayName("Класс AuthorManageSevice") +@RunWith(SpringRunner.class) +@ComponentScan("ru.otus.mkulikov.app") +@DataJpaTest +@TestPropertySource(locations= "classpath:application.yml") +class AuthorManageSeviceImplTest { + + @Autowired + private AuthorManageService authorManageService; + + @Test + @DisplayName("Получение автора по id") + void getAuthorById() { + Author author = authorManageService.getAuthorById(1L); + + assertAll( + "author", + () -> assertNotNull(author), + () -> assertEquals(1L, author.getId()), + () -> assertEquals("Surname", author.getSurname()), + () -> assertEquals("FirstName", author.getFirstName()), + () -> assertEquals("SecondName", author.getSecondName()) + ); + } + + @Test + @DisplayName("Получение всех авторов") + void getAuthors() { + List authors = authorManageService.getAuthors(); + + assertAll( + "authors", + () -> assertNotNull(authors), + () -> assertEquals(3, authors.size()), + () -> assertEquals("Surname", authors.get(0).getSurname()), + () -> assertEquals("Surname2", authors.get(1).getSurname()), + () -> assertEquals("Surname3", authors.get(2).getSurname()) + ); + } + + @Test + @DisplayName("Добавление автора") + void addAuthor() { + int count = authorManageService.addAuthor("TestSurname", "TestFirstName", "TestSecondName"); + Author author_selected = authorManageService.getAuthorById(4L); + + assertAll( + "author", + () -> assertNotNull(author_selected), + () -> assertEquals(1, count), + () -> assertEquals(4L, author_selected.getId()), + () -> assertEquals("TestSurname", author_selected.getSurname()), + () -> assertEquals("TestFirstName", author_selected.getFirstName()), + () -> assertEquals("TestSecondName", author_selected.getSecondName()) + ); + } + + @Test + @DisplayName("Обновление автора") + void updateAuthor() { + Author author1 = authorManageService.getAuthorById(1L); + int count = authorManageService.updateAuthor(1L, "TestSurname", "TestFirstName", "TestSecondName"); + Author author2 = authorManageService.getAuthorById(1L); + + assertAll( + "author", + () -> assertEquals(1, count), + () -> assertEquals("Surname", author1.getSurname()), + () -> assertEquals("FirstName", author1.getFirstName()), + () -> assertEquals("SecondName", author1.getSecondName()), + () -> assertEquals("TestSurname", author2.getSurname()), + () -> assertEquals("TestFirstName", author2.getFirstName()), + () -> assertEquals("TestSecondName", author2.getSecondName()) + ); + } + + @Test + @DisplayName("Удаление автора, который используется в таблице книг") + void deleteAuthor() { + assertThrows(PersistenceException.class, () -> { authorManageService.deleteAuthor(1L); }); + } +} diff --git a/src/test/java/ru/otus/mkulikov/app/service/BookManageSeviceImplTest.java b/src/test/java/ru/otus/mkulikov/app/service/BookManageSeviceImplTest.java new file mode 100644 index 0000000..5dbb053 --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/app/service/BookManageSeviceImplTest.java @@ -0,0 +1,116 @@ +package ru.otus.mkulikov.app.service; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import ru.otus.mkulikov.app.model.Book; +import ru.otus.mkulikov.app.utils.DateUtil; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 29.05.2019 + * Time: 13:40 + */ + +@DisplayName("Класс BookManageSevice") +@RunWith(SpringRunner.class) +@ComponentScan("ru.otus.mkulikov.app") +@DataJpaTest +@TestPropertySource(locations= "classpath:application.yml") +class BookManageSeviceImplTest { + + @Autowired + private BookManageSevice booksManageSevice; + + @Test + @DisplayName("Получение книги по id") + void getBookById() { + Book book = booksManageSevice.getBookById(1L); + + assertAll( + "book", + () -> assertNotNull(book), + () -> assertNotNull(book.getAuthor()), + () -> assertNotNull(book.getGenre()), + () -> assertEquals(1L, book.getId()), + () -> assertEquals("2019-01-01", DateUtil.dateToString(book.getAddRecordDate())), + () -> assertEquals("book_1", book.getCaption()), + () -> assertEquals(1, book.getAuthor().getId()), + () -> assertEquals(1, book.getGenre().getId()), + () -> assertEquals("description", book.getDescription()) + ); + } + + @Test + @DisplayName("Получение всех книг") + void getBooks() { + List books = booksManageSevice.getBooks(); + + assertAll( + "books", + () -> assertNotNull(books), + () -> assertEquals(3, books.size()), + () -> assertEquals("book_1", books.get(0).getCaption()), + () -> assertEquals("book_2", books.get(1).getCaption()), + () -> assertEquals("book_3", books.get(2).getCaption()) + ); + } + + @Test + @DisplayName("Добавление книги") + void addBook() { + int count = booksManageSevice.addBook("Test_Book", 2, 3, "Test_Description"); + Book book = booksManageSevice.getBookById(4L); + + assertAll( + "book", + () -> assertNotNull(book), + () -> assertEquals(1, count), + () -> assertEquals(4L, book.getId()), + () -> assertEquals("Test_Book", book.getCaption()), + () -> assertEquals(2, book.getAuthor().getId()), + () -> assertEquals(3, book.getGenre().getId()), + () -> assertEquals("Test_Description", book.getDescription()) + ); + } + + @Test + @DisplayName("Обновление книги") + void updateBook() { + Book book1 = booksManageSevice.getBookById(1L); + int count = booksManageSevice.updateBook(1L, "Test_Book", 2, 3, "Test_Description"); + Book book2 = booksManageSevice.getBookById(1L); + + assertAll( + "book", + () -> assertEquals(1, count), + () -> assertEquals("book_1", book1.getCaption()), + () -> assertEquals("description", book1.getDescription()), + () -> assertEquals("Test_Book", book2.getCaption()), + () -> assertEquals("Test_Description", book2.getDescription()) + ); + } + + @Test + @DisplayName("Удаление книги по id") + void deleteBook() { + int count = booksManageSevice.deleteBook(1L); + + assertAll( + "book", + () -> assertEquals(1, count), + () -> assertThrows(IndexOutOfBoundsException.class, () -> { booksManageSevice.getBookById(1L); }) + ); + } + +} \ No newline at end of file diff --git a/src/test/java/ru/otus/mkulikov/app/service/CommentManageSeviceImplTest.java b/src/test/java/ru/otus/mkulikov/app/service/CommentManageSeviceImplTest.java new file mode 100644 index 0000000..e641616 --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/app/service/CommentManageSeviceImplTest.java @@ -0,0 +1,126 @@ +package ru.otus.mkulikov.app.service; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import ru.otus.mkulikov.app.model.Comment; +import ru.otus.mkulikov.app.utils.DateUtil; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 15:56 + */ + +@DisplayName("Класс CommentManageSevice") +@RunWith(SpringRunner.class) +@ComponentScan("ru.otus.mkulikov.app") +@DataJpaTest +@TestPropertySource(locations= "classpath:application.yml") +class CommentManageSeviceImplTest { + + @Autowired + private CommentManageService commentManageService; + + @Test + @DisplayName("Получение комментария по id") + void getCommentById() { + Comment comment = commentManageService.getCommentById(1L); + + assertAll( + "comment", + () -> assertNotNull(comment), + () -> assertNotNull(comment.getBook()), + () -> assertEquals(1L, comment.getId()), + () -> assertEquals("user1", comment.getUserName()), + () -> assertEquals("2019-01-01 10:01:01", DateUtil.dateTimeToString(comment.getAddRecordDate())), + () -> assertEquals("text1", comment.getText()) + ); + } + + @Test + @DisplayName("Получение всех комментариев") + void getComments() { + List comments = commentManageService.getComments(); + + assertAll( + "comments", + () -> assertNotNull(comments), + () -> assertEquals(4, comments.size()), + () -> assertEquals("text1", comments.get(0).getText()), + () -> assertEquals("text2", comments.get(1).getText()), + () -> assertEquals("text3", comments.get(2).getText()), + () -> assertEquals("text4", comments.get(3).getText()) + ); + } + + @Test + @DisplayName("Добавление комментария") + void addComment() { + int count = commentManageService.addComment(1L, "user5", "text5"); + + Comment comment = commentManageService.getCommentById(5L); + + assertAll( + "comment", + () -> assertNotNull(comment), + () -> assertNotNull(comment.getBook()), + () -> assertEquals(1, count), + () -> assertEquals(5L, comment.getId()), + () -> assertEquals("user5", comment.getUserName()), + () -> assertEquals("text5", comment.getText()) + ); + } + + @Test + @DisplayName("Получение комментариев по Id книги") + void getCommentsByBookId() { + List comments = commentManageService.getCommentsByBookId(1L); + + assertAll( + "comments", + () -> assertNotNull(comments), + () -> assertEquals(2, comments.size()), + () -> assertEquals("text1", comments.get(0).getText()), + () -> assertEquals("text2", comments.get(1).getText()) + ); + } + + @Test + @DisplayName("Обновление комментария") + void updateComment() { + Comment comment1 = commentManageService.getCommentById(1L); + int count = commentManageService.updateComment(1L, "TestUser", "TestText"); + Comment comment2 = commentManageService.getCommentById(1L); + + assertAll( + "comment", + () -> assertNotNull(comment1), + () -> assertNotNull(comment2), + () -> assertNotNull(comment1.getBook()), + () -> assertNotNull(comment2.getBook()), + () -> assertEquals(1, count), + () -> assertEquals("user1", comment1.getUserName()), + () -> assertEquals("text1", comment1.getText()), + () -> assertEquals("TestUser", comment2.getUserName()), + () -> assertEquals("TestText", comment2.getText()) + ); + } + + @Test + @DisplayName("Удаление комментария") + void deleteComment() { + commentManageService.deleteComment(1L); + assertNull(commentManageService.getCommentById(1L)); + } +} diff --git a/src/test/java/ru/otus/mkulikov/app/service/GenreManageSeviceImplTest.java b/src/test/java/ru/otus/mkulikov/app/service/GenreManageSeviceImplTest.java new file mode 100644 index 0000000..da4d95f --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/app/service/GenreManageSeviceImplTest.java @@ -0,0 +1,98 @@ +package ru.otus.mkulikov.app.service; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import ru.otus.mkulikov.app.model.Genre; + +import javax.persistence.PersistenceException; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 30.05.2019 + * Time: 15:56 + */ + +@DisplayName("Класс GenreManageSevice") +@RunWith(SpringRunner.class) +@ComponentScan("ru.otus.mkulikov.app") +@DataJpaTest +@TestPropertySource(locations= "classpath:application.yml") +class GenreManageSeviceImplTest { + + @Autowired + private GenreManageService genreManageService; + + @Test + @DisplayName("Получение жанра по id") + void getGenreById() { + Genre genre = genreManageService.getGenreById(1L); + + assertAll( + "genre", + () -> assertNotNull(genre), + () -> assertEquals(1L, genre.getId()), + () -> assertEquals("Genre1", genre.getName()) + ); + } + + @Test + @DisplayName("Получение всех жанров") + void getGenres() { + List genres = genreManageService.getGenres(); + + assertAll( + "genres", + () -> assertNotNull(genres), + () -> assertEquals(3, genres.size()), + () -> assertEquals("Genre1", genres.get(0).getName()), + () -> assertEquals("Genre2", genres.get(1).getName()), + () -> assertEquals("Genre3", genres.get(2).getName()) + ); + } + + @Test + @DisplayName("Добавление жанра") + void addGenre() { + int count = genreManageService.addGenre("Test4"); + Genre genre = genreManageService.getGenreById(4L); + + assertAll( + "genre", + () -> assertNotNull(genre), + () -> assertEquals(1, count), + () -> assertEquals(4L, genre.getId()), + () -> assertEquals("Test4", genre.getName()) + ); + } + + @Test + @DisplayName("Обновление жанра") + void updateGenre() { + Genre genre1 = genreManageService.getGenreById(1L); + int count = genreManageService.updateGenre(1L, "UpdatedName"); + Genre genre2 = genreManageService.getGenreById(1L); + + assertAll( + "genre", + () -> assertEquals(1, count), + () -> assertEquals("Genre1", genre1.getName()), + () -> assertEquals("UpdatedName", genre2.getName()) + ); + } + + @Test + @DisplayName("Удаление жанра, который используется в таблице книг") + void deleteGenre() { + assertThrows(PersistenceException.class, () -> { genreManageService.deleteGenre(1L); }); + } +} diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml new file mode 100644 index 0000000..6175668 --- /dev/null +++ b/src/test/resources/application.yml @@ -0,0 +1,17 @@ +spring: + banner: + location: "classpath:banner-test.txt" + + datasource: + initialization-mode: always + platform: test + + jpa: + hibernate: + ddl-auto: none + + properties: + hibernate: + show_sql: true + format_sql: true + diff --git a/src/test/resources/banner-test.txt b/src/test/resources/banner-test.txt new file mode 100644 index 0000000..50a692c --- /dev/null +++ b/src/test/resources/banner-test.txt @@ -0,0 +1,11 @@ + ___ ___ ___ ___ ___ ___ ___ + /\__\ /\ \ /\__\ /\ \ /\ \ ___ / /\ / /\ ___ + /:/ / /::\ \ /:/ / /::\ \ /::\ \ /__/\ / /::\ / /::\ /__/\ + /:/ / /:/\:\ \ /:/ / /:/\:\ \ /:/\ \ \ \ \:\ / /:/\:\ /__/:/\:\ \ \:\ + /:/ / ___ /:/ \:\ \ /:/ / /::\~\:\ \ _\:\~\ \ \ \__\:\ / /::\ \:\ _\_ \:\ \:\ \__\:\ + /:/__/ /\__\ /:/__/ \:\__\ /:/__/ /:/\:\ \:\__\ /\ \:\ \ \__\ *** / /::\ /__/:/\:\ \:\ /__/\ \:\ \:\ / /::\ + \:\ \ /:/ / \:\ \ /:/ / \:\ \ \:\~\:\ \/__/ \:\ \:\ \/__/ / /:/\:\ \ \:\ \:\_\/ \ \:\ \:\_\/ / /:/\:\ + \:\ /:/ / \:\ /:/ / \:\ \ \:\ \:\__\ \:\ \:\__\ / /:/__\/ \ \:\ \:\ \ \:\_\:\ / /:/__\/ + \:\/:/ / \:\/:/ / \:\ \ \:\ \/__/ \:\/:/ / /__/:/ \ \:\_\/ \ \:\/:/ /__/:/ + \::/ / \::/ / \:\__\ \:\__\ \::/ / \__\/ \ \:\ \ \::/ \__\/ + \/__/ \/__/ \/__/ \/__/ \/__/ \__\/ \__\/ diff --git a/src/test/resources/data-test.sql b/src/test/resources/data-test.sql new file mode 100644 index 0000000..75ebe2d --- /dev/null +++ b/src/test/resources/data-test.sql @@ -0,0 +1,39 @@ +insert into AUTHOR (ID, SURNAME, FIRST_NAME, SECOND_NAME) +values (sq_author.nextval, 'Surname', 'FirstName', 'SecondName'); + +insert into AUTHOR (ID, SURNAME, FIRST_NAME, SECOND_NAME) +values (sq_author.nextval, 'Surname2', 'FirstName2', 'SecondName2'); + +insert into AUTHOR (ID, SURNAME, FIRST_NAME, SECOND_NAME) +values (sq_author.nextval, 'Surname3', 'FirstName3', 'SecondName3'); + +-------------------------- + +insert into GENRE (ID, NAME) values (sq_genre.nextval, 'Genre1'); +insert into GENRE (ID, NAME) values (sq_genre.nextval, 'Genre2'); +insert into GENRE (ID, NAME) values (sq_genre.nextval, 'Genre3'); + +-------------------------- + +insert into BOOK (ID, ADD_RECORD_DATE, CAPTION, AUTHOR_ID, GENRE_ID, DESCRIPTION) +values (sq_book.nextval, to_date('2019-01-01','YYYY-MM-DD'), 'book_1', 1, 1, 'description'); + +insert into BOOK (ID, ADD_RECORD_DATE, CAPTION, AUTHOR_ID, GENRE_ID, DESCRIPTION) +values (sq_book.nextval, to_date('2019-01-01','YYYY-MM-DD'), 'book_2', 1, 1, 'description'); + +insert into BOOK (ID, ADD_RECORD_DATE, CAPTION, AUTHOR_ID, GENRE_ID, DESCRIPTION) +values (sq_book.nextval, to_date('2019-01-01','YYYY-MM-DD'), 'book_3', 1, 1, 'description'); + +-------------------------- + +insert into COMMENT (ID, BOOK_ID, ADD_RECORD_DATE, USER_NAME, TEXT) +values (sq_comment.nextval, 1, to_date('2019-01-01 10:01:01','YYYY-MM-DD HH24-MI-SS'), 'user1', 'text1'); + +insert into COMMENT (ID, BOOK_ID, ADD_RECORD_DATE, USER_NAME, TEXT) +values (sq_comment.nextval, 1, to_date('2019-01-01 10:01:02','YYYY-MM-DD HH24-MI-SS'), 'user2', 'text2'); + +insert into COMMENT (ID, BOOK_ID, ADD_RECORD_DATE, USER_NAME, TEXT) +values (sq_comment.nextval, 2, to_date('2019-01-01 10:01:03','YYYY-MM-DD HH24-MI-SS'), 'user3', 'text3'); + +insert into COMMENT (ID, BOOK_ID, ADD_RECORD_DATE, USER_NAME, TEXT) +values (sq_comment.nextval, 2, to_date('2019-01-01 10:01:04','YYYY-MM-DD HH24-MI-SS'), 'user4', 'text4'); \ No newline at end of file diff --git a/src/test/resources/schema-test.sql b/src/test/resources/schema-test.sql new file mode 100644 index 0000000..7156478 --- /dev/null +++ b/src/test/resources/schema-test.sql @@ -0,0 +1,43 @@ +DROP TABLE IF EXISTS BOOK; +DROP TABLE IF EXISTS AUTHOR; +DROP TABLE IF EXISTS GENRE; +DROP TABLE IF EXISTS COMMENT; + +CREATE TABLE AUTHOR( + ID NUMBER(20,0) PRIMARY KEY not null, + SURNAME VARCHAR(100) not null, + FIRST_NAME VARCHAR(100) not null, + SECOND_NAME VARCHAR(100) +); + +CREATE TABLE GENRE( + ID NUMBER(20,0) PRIMARY KEY not null, + NAME VARCHAR(100) not null +); + +CREATE TABLE BOOK( + ID NUMBER(20,0) PRIMARY KEY not null, + ADD_RECORD_DATE DATE default sysdate, + CAPTION VARCHAR(255) not null, + AUTHOR_ID NUMBER(20,0) not null, + GENRE_ID NUMBER(20,0) not null, + DESCRIPTION VARCHAR(255), + + foreign key (AUTHOR_ID) references AUTHOR(ID), + foreign key (GENRE_ID) references GENRE(ID) +); + +CREATE TABLE COMMENT( + ID NUMBER(20,0) PRIMARY KEY not null, + BOOK_ID NUMBER(20,0) not null, + ADD_RECORD_DATE TIMESTAMP default sysdate, + USER_NAME VARCHAR(20), + TEXT VARCHAR(500), + + foreign key (BOOK_ID) references BOOK(ID) ON DELETE CASCADE +); + +CREATE SEQUENCE sq_author minvalue 1 start with 1 increment by 1; +CREATE SEQUENCE sq_genre minvalue 1 start with 1 increment by 1; +CREATE SEQUENCE sq_book minvalue 1 start with 1 increment by 1; +CREATE SEQUENCE sq_comment minvalue 1 start with 1 increment by 1; \ No newline at end of file