From 7c9740ed4c5686d80f947d3a9504d155aeb46e2d Mon Sep 17 00:00:00 2001 From: rainett <96131229+rainett@users.noreply.github.com> Date: Tue, 3 Sep 2024 19:12:16 +0300 Subject: [PATCH 1/3] Implemented DAO and model for Book entity --- pom.xml | 8 ++ src/main/java/mate/academy/Main.java | 39 ++++++ src/main/java/mate/academy/dao/BookDao.java | 17 +++ .../mate/academy/dao/impl/BookDaoImpl.java | 117 ++++++++++++++++++ .../exceptions/DataProcessingException.java | 11 ++ src/main/java/mate/academy/lib/Dao.java | 3 + src/main/java/mate/academy/model/Book.java | 47 +++++++ .../mate/academy/util/ConnectionUtil.java | 30 +++++ src/main/resources/init_db.sql | 5 + 9 files changed, 277 insertions(+) create mode 100644 src/main/java/mate/academy/dao/BookDao.java create mode 100644 src/main/java/mate/academy/dao/impl/BookDaoImpl.java create mode 100644 src/main/java/mate/academy/exceptions/DataProcessingException.java create mode 100644 src/main/java/mate/academy/model/Book.java create mode 100644 src/main/java/mate/academy/util/ConnectionUtil.java create mode 100644 src/main/resources/init_db.sql diff --git a/pom.xml b/pom.xml index 683e84ec..e2ffb51a 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,14 @@ + + + mysql + mysql-connector-java + 8.0.30 + + + diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java index 0058fbf9..37f3136e 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -1,7 +1,46 @@ package mate.academy; +import java.math.BigDecimal; +import java.util.List; +import mate.academy.dao.BookDao; +import mate.academy.lib.Injector; +import mate.academy.model.Book; + public class Main { + private static final Injector injector = Injector.getInstance("mate.academy"); + public static void main(String[] args) { + BookDao bookDao = (BookDao) injector.getInstance(BookDao.class); + List books = List.of( + new Book(null, "Book1", new BigDecimal(100)), + new Book(null, "Book2", new BigDecimal(150)), + new Book(null, "Book3", new BigDecimal(50)) + ); + + books.forEach(bookDao::create); + System.out.println("Created books:"); + books.forEach(System.out::println); + System.out.println(); + + Long bookId = 2L; + System.out.println("Book with id = [" + bookId + "]"); + bookDao.findById(bookId).ifPresent(System.out::println); + System.out.println(); + + System.out.println("All books in the table:"); + bookDao.findAll().forEach(System.out::println); + System.out.println(); + + Book anyBook = books.stream().findAny().orElseThrow(); + anyBook.setTitle("Updated title"); + Book anyUpdatedBook = bookDao.update(anyBook); + System.out.println("Updated book:"); + System.out.println(anyUpdatedBook); + System.out.println(); + boolean isDeleted = bookDao.deleteById(anyUpdatedBook.getId()); + System.out.println("Is book with id = [" + + anyUpdatedBook.getId() + "] deleted = [" + + isDeleted + "]"); } } diff --git a/src/main/java/mate/academy/dao/BookDao.java b/src/main/java/mate/academy/dao/BookDao.java new file mode 100644 index 00000000..d60c063d --- /dev/null +++ b/src/main/java/mate/academy/dao/BookDao.java @@ -0,0 +1,17 @@ +package mate.academy.dao; + +import java.util.List; +import java.util.Optional; +import mate.academy.model.Book; + +public interface BookDao { + Book create(Book book); + + Optional findById(Long id); + + List findAll(); + + Book update(Book book); + + boolean deleteById(Long id); +} diff --git a/src/main/java/mate/academy/dao/impl/BookDaoImpl.java b/src/main/java/mate/academy/dao/impl/BookDaoImpl.java new file mode 100644 index 00000000..8accc494 --- /dev/null +++ b/src/main/java/mate/academy/dao/impl/BookDaoImpl.java @@ -0,0 +1,117 @@ +package mate.academy.dao.impl; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import mate.academy.dao.BookDao; +import mate.academy.exceptions.DataProcessingException; +import mate.academy.lib.Dao; +import mate.academy.model.Book; +import mate.academy.util.ConnectionUtil; + +@Dao +public class BookDaoImpl implements BookDao { + @Override + public Book create(Book book) { + String query = "INSERT INTO books(title, price) VALUES (?, ?)"; + try (Connection connection = ConnectionUtil.getConnection()) { + PreparedStatement statement = + connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS); + statement.setString(1, book.getTitle()); + statement.setBigDecimal(2, book.getPrice()); + + int affectedRows = statement.executeUpdate(); + if (affectedRows < 1) { + throw new DataProcessingException("Expected to affect at least one row, " + + "but got affected = [" + affectedRows + "]"); + } + ResultSet resultSet = statement.getGeneratedKeys(); + if (resultSet.next()) { + Long id = resultSet.getLong(1); + book.setId(id); + } + } catch (SQLException e) { + throw new DataProcessingException("Failed to create a book = [" + book + "]", e); + } + return book; + } + + @Override + public Optional findById(Long id) { + String query = "SELECT * FROM books WHERE id = ?"; + try (Connection connection = ConnectionUtil.getConnection()) { + PreparedStatement statement = connection.prepareStatement(query); + statement.setLong(1, id); + ResultSet resultSet = statement.executeQuery(); + if (resultSet.next()) { + Book book = getBookFromResultSet(resultSet); + return Optional.of(book); + } + } catch (SQLException e) { + throw new DataProcessingException("Failed to find a book with id = [" + id + "]", e); + } + return Optional.empty(); + } + + @Override + public List findAll() { + String query = "SELECT * FROM books"; + List books = new ArrayList<>(); + try (Connection connection = ConnectionUtil.getConnection()) { + PreparedStatement statement = connection.prepareStatement(query); + ResultSet resultSet = statement.executeQuery(); + while (resultSet.next()) { + Book book = getBookFromResultSet(resultSet); + books.add(book); + } + } catch (SQLException e) { + throw new DataProcessingException("Failed to fetch all books", e); + } + return books; + } + + @Override + public Book update(Book book) { + String query = "UPDATE books SET title = ?, price = ? WHERE id = ?"; + try (Connection connection = ConnectionUtil.getConnection()) { + PreparedStatement statement = connection.prepareStatement(query); + statement.setString(1, book.getTitle()); + statement.setBigDecimal(2, book.getPrice()); + statement.setLong(3, book.getId()); + int affectedRows = statement.executeUpdate(); + if (affectedRows < 1) { + throw new DataProcessingException("Expected to affect at least one row, " + + "but got affected = [" + affectedRows + "]"); + } + } catch (SQLException e) { + throw new DataProcessingException("Failed to update a book = [" + book + "]", e); + } + return book; + } + + @Override + public boolean deleteById(Long id) { + String query = "DELETE FROM books WHERE id = ?"; + try (Connection connection = ConnectionUtil.getConnection()) { + PreparedStatement statement = connection.prepareStatement(query); + statement.setLong(1, id); + return statement.executeUpdate() > 0; + } catch (SQLException e) { + throw new DataProcessingException("Failed to delete a book " + + "with id = [" + id + "]", e); + } + } + + private Book getBookFromResultSet(ResultSet resultSet) throws SQLException { + Long id = resultSet.getObject("id", Long.class); + String title = resultSet.getString("title"); + BigDecimal price = resultSet.getBigDecimal("price"); + return new Book(id, title, price); + } +} diff --git a/src/main/java/mate/academy/exceptions/DataProcessingException.java b/src/main/java/mate/academy/exceptions/DataProcessingException.java new file mode 100644 index 00000000..b39d20ac --- /dev/null +++ b/src/main/java/mate/academy/exceptions/DataProcessingException.java @@ -0,0 +1,11 @@ +package mate.academy.exceptions; + +public class DataProcessingException extends RuntimeException { + public DataProcessingException(String message, Throwable e) { + super(message, e); + } + + public DataProcessingException(String message) { + super(message); + } +} diff --git a/src/main/java/mate/academy/lib/Dao.java b/src/main/java/mate/academy/lib/Dao.java index f558d09a..6c89c709 100644 --- a/src/main/java/mate/academy/lib/Dao.java +++ b/src/main/java/mate/academy/lib/Dao.java @@ -1,8 +1,11 @@ package mate.academy.lib; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Dao { } diff --git a/src/main/java/mate/academy/model/Book.java b/src/main/java/mate/academy/model/Book.java new file mode 100644 index 00000000..d8828575 --- /dev/null +++ b/src/main/java/mate/academy/model/Book.java @@ -0,0 +1,47 @@ +package mate.academy.model; + +import java.math.BigDecimal; + +public class Book { + private Long id; + private String title; + private BigDecimal price; + + public Book(Long id, String title, BigDecimal price) { + this.id = id; + this.title = title; + this.price = price; + } + + 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 BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + @Override + public String toString() { + return "Book{" + + "id=" + id + + ", title='" + title + '\'' + + ", price=" + price + '}'; + } +} diff --git a/src/main/java/mate/academy/util/ConnectionUtil.java b/src/main/java/mate/academy/util/ConnectionUtil.java new file mode 100644 index 00000000..1577605a --- /dev/null +++ b/src/main/java/mate/academy/util/ConnectionUtil.java @@ -0,0 +1,30 @@ +package mate.academy.util; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; +import mate.academy.exceptions.DataProcessingException; + +public class ConnectionUtil { + private static final Properties DB_PROPERTIES; + private static final String URL = "jdbc:mysql://localhost:3306/mate"; + private static final String USER = "root"; + private static final String PASSWORD = "password"; + private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; + + static { + DB_PROPERTIES = new Properties(); + DB_PROPERTIES.put("user", USER); + DB_PROPERTIES.put("password", PASSWORD); + try { + Class.forName(DRIVER); + } catch (ClassNotFoundException e) { + throw new DataProcessingException("Failed to load JDBC driver", e); + } + } + + public static Connection getConnection() throws SQLException { + return DriverManager.getConnection(URL, DB_PROPERTIES); + } +} diff --git a/src/main/resources/init_db.sql b/src/main/resources/init_db.sql new file mode 100644 index 00000000..7b752a67 --- /dev/null +++ b/src/main/resources/init_db.sql @@ -0,0 +1,5 @@ +CREATE TABLE books( + id bigint AUTO_INCREMENT PRIMARY KEY, + title varchar(255) NOT NULL, + price DECIMAL(10, 2) NOT NULL +); \ No newline at end of file From a714556f0b7410ab2717b427556e87a21dc54634 Mon Sep 17 00:00:00 2001 From: rainett <96131229+rainett@users.noreply.github.com> Date: Tue, 3 Sep 2024 19:14:03 +0300 Subject: [PATCH 2/3] removed redundant break --- src/main/java/mate/academy/dao/impl/BookDaoImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/mate/academy/dao/impl/BookDaoImpl.java b/src/main/java/mate/academy/dao/impl/BookDaoImpl.java index 8accc494..3f9e8e7b 100644 --- a/src/main/java/mate/academy/dao/impl/BookDaoImpl.java +++ b/src/main/java/mate/academy/dao/impl/BookDaoImpl.java @@ -25,7 +25,6 @@ public Book create(Book book) { connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS); statement.setString(1, book.getTitle()); statement.setBigDecimal(2, book.getPrice()); - int affectedRows = statement.executeUpdate(); if (affectedRows < 1) { throw new DataProcessingException("Expected to affect at least one row, " From 4d0c6bc1db5c5f9864722c00c55e4858a7517c5d Mon Sep 17 00:00:00 2001 From: rainett <96131229+rainett@users.noreply.github.com> Date: Tue, 3 Sep 2024 19:20:21 +0300 Subject: [PATCH 3/3] moved from getLong to getObject in BookDaoImpl --- src/main/java/mate/academy/dao/impl/BookDaoImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mate/academy/dao/impl/BookDaoImpl.java b/src/main/java/mate/academy/dao/impl/BookDaoImpl.java index 3f9e8e7b..cc26df57 100644 --- a/src/main/java/mate/academy/dao/impl/BookDaoImpl.java +++ b/src/main/java/mate/academy/dao/impl/BookDaoImpl.java @@ -32,7 +32,7 @@ public Book create(Book book) { } ResultSet resultSet = statement.getGeneratedKeys(); if (resultSet.next()) { - Long id = resultSet.getLong(1); + Long id = resultSet.getObject(1, Long.class); book.setId(id); } } catch (SQLException e) {