From 74e7a1c4e1e156f69f727f310a4faebfd19c3d51 Mon Sep 17 00:00:00 2001 From: Nikolai Date: Mon, 9 Sep 2024 18:52:02 +0300 Subject: [PATCH 1/4] Added task solution --- pom.xml | 7 ++ src/main/java/mate/academy/Main.java | 20 +++ src/main/java/mate/academy/dao/BookDao.java | 19 +++ .../java/mate/academy/dao/BookDaoImpl.java | 116 ++++++++++++++++++ .../exception/DataProcessingException.java | 7 ++ src/main/java/mate/academy/model/Book.java | 42 +++++++ .../mate/academy/util/ConnectionUtil.java | 27 ++++ src/main/resources/init_db.sql | 16 +++ 8 files changed, 254 insertions(+) create mode 100644 src/main/java/mate/academy/dao/BookDao.java create mode 100644 src/main/java/mate/academy/dao/BookDaoImpl.java create mode 100644 src/main/java/mate/academy/exception/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..d84ed3aa 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,13 @@ https://raw.githubusercontent.com/mate-academy/style-guides/master/java/checkstyle.xml + + + mysql + mysql-connector-java + 8.0.33 + + diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java index 0058fbf9..7c09dbea 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -1,7 +1,27 @@ package mate.academy; +import java.math.BigDecimal; +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); + Book book = new Book(); + book.setTitle("Java Programming"); + book.setPrice(new BigDecimal(200)); + bookDao.create(book); + bookDao.findAll().forEach(System.out::println); + System.out.println(); + System.out.println("Id 1 " + System.lineSeparator() + bookDao.findById(1L)); + bookDao.deleteById(2L); + bookDao.findAll().forEach(System.out::println); + System.out.println(); + bookDao.update(book); + bookDao.findAll().forEach(System.out::println); } } 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..54263faf --- /dev/null +++ b/src/main/java/mate/academy/dao/BookDao.java @@ -0,0 +1,19 @@ +package mate.academy.dao; + +import java.util.List; +import java.util.Optional; +import mate.academy.lib.Dao; +import mate.academy.model.Book; + +@Dao +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/BookDaoImpl.java b/src/main/java/mate/academy/dao/BookDaoImpl.java new file mode 100644 index 00000000..5c3d9115 --- /dev/null +++ b/src/main/java/mate/academy/dao/BookDaoImpl.java @@ -0,0 +1,116 @@ +package mate.academy.dao; + +import java.math.BigDecimal; +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.exception.DataProcessingException; +import mate.academy.lib.Dao; +import mate.academy.model.Book; +import mate.academy.util.ConnectionUtil; + +@Dao +public class BookDaoImpl implements BookDao { + + public Book create(Book book) { + String sql = "INSERT INTO books (title, price) VALUES (?, ?)"; + + try (PreparedStatement statement = ConnectionUtil.getConnection().prepareStatement(sql, + Statement.RETURN_GENERATED_KEYS)) { + statement.setString(1, book.getTitle()); + statement.setBigDecimal(2, book.getPrice()); + + int affectedRows = statement.executeUpdate(); + + if (affectedRows == 0) { + throw new SQLException("Creating book failed, no rows affected."); + } + + try (ResultSet generatedKeys = statement.getGeneratedKeys()) { + if (generatedKeys.next()) { + book.setId(generatedKeys.getLong(1)); + } else { + throw new SQLException("Creating book failed, no ID obtained."); + } + } + } catch (SQLException e) { + throw new DataProcessingException("Can't create book " + book, e); + } + + return book; + } + + public Optional findById(Long id) { + String sql = "SELECT * FROM books WHERE id = ?"; + + try (PreparedStatement statement = ConnectionUtil.getConnection().prepareStatement(sql)) { + statement.setLong(1, id); + + try (ResultSet resultSet = statement.executeQuery()) { + if (resultSet.next()) { + Book book = new Book(); + book.setId(resultSet.getObject("id", Long.class)); + book.setPrice(resultSet.getObject("price", BigDecimal.class)); + book.setTitle(resultSet.getString("title")); + return Optional.of(book); + } + } + } catch (SQLException e) { + throw new DataProcessingException("Can't find by id for id = " + id, e); + } + + return Optional.empty(); + } + + public List findAll() { + List books = new ArrayList<>(); + String sql = "SELECT * FROM books"; + + try (PreparedStatement statement = ConnectionUtil.getConnection().prepareStatement(sql); + ResultSet resultSet = statement.executeQuery()) { + + while (resultSet.next()) { + Book book = new Book(); + book.setId(resultSet.getObject("id", Long.class)); + book.setPrice(resultSet.getObject("price", BigDecimal.class)); + book.setTitle(resultSet.getString("title")); + books.add(book); + } + } catch (SQLException e) { + throw new DataProcessingException("Can't retrieve all books", e); + } + + return books; + } + + public Book update(Book book) { + String sql = "UPDATE books SET price = ?, title = ? WHERE id = ?"; + try (PreparedStatement statement = ConnectionUtil.getConnection().prepareStatement(sql)) { + statement.setBigDecimal(1, book.getPrice()); + statement.setString(2, book.getTitle()); + statement.setLong(3, book.getId()); + if (statement.executeUpdate() > 0) { + return book; + } else { + throw new DataProcessingException("No book found with id = " + book.getId(), + new RuntimeException()); + } + } catch (SQLException e) { + throw new DataProcessingException("Can't update book with id = " + book.getId(), e); + } + } + + public boolean deleteById(Long id) { + String sql = "DELETE FROM books WHERE id = ?"; + try (PreparedStatement statement = ConnectionUtil.getConnection().prepareStatement(sql)) { + statement.setLong(1, id); + return statement.executeUpdate() > 0; + } catch (SQLException e) { + throw new DataProcessingException("Can't delete book with id = " + id, e); + } + } +} diff --git a/src/main/java/mate/academy/exception/DataProcessingException.java b/src/main/java/mate/academy/exception/DataProcessingException.java new file mode 100644 index 00000000..de9b45dc --- /dev/null +++ b/src/main/java/mate/academy/exception/DataProcessingException.java @@ -0,0 +1,7 @@ +package mate.academy.exception; + +public class DataProcessingException extends RuntimeException { + public DataProcessingException(String message, Throwable ex) { + super(message, ex); + } +} 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..6c956774 --- /dev/null +++ b/src/main/java/mate/academy/model/Book.java @@ -0,0 +1,42 @@ +package mate.academy.model; + +import java.math.BigDecimal; + +public class Book { + private Long id; + private String title; + private BigDecimal price; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @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..799e8e01 --- /dev/null +++ b/src/main/java/mate/academy/util/ConnectionUtil.java @@ -0,0 +1,27 @@ +package mate.academy.util; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; + +public class ConnectionUtil { + private static final String DB_URL = "jdbc:mysql://localhost:3306/bookstore"; + private static final Properties DB_PROPERTIES; + + static { + DB_PROPERTIES = new Properties(); + DB_PROPERTIES.put("user", "root"); + DB_PROPERTIES.put("password", "qwertyasd"); + + try { + Class.forName("com.mysql.cj.jdbc.Driver"); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Can not load JDBC", e); + } + } + + public static Connection getConnection() throws SQLException { + return DriverManager.getConnection(DB_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..60beb762 --- /dev/null +++ b/src/main/resources/init_db.sql @@ -0,0 +1,16 @@ +CREATE DATABASE IF NOT EXISTS BookStore DEFAULT CHARACTER SET utf8; + +USE BookStore; + +CREATE TABLE Books ( + id BIGINT NOT NULL AUTO_INCREMENT, + title VARCHAR(255) NOT NULL, + price DECIMAL(10, 2) NOT NULL, + PRIMARY KEY (id) + ); + +INSERT INTO Books (title, price) VALUES ('The Great Gatsby', 10.99); +INSERT INTO Books (title, price) VALUES ('1984', 8.99); +INSERT INTO Books (title, price) VALUES ('To Kill a Mockingbird', 12.50); +INSERT INTO Books (title, price) VALUES ('Pride and Prejudice', 9.75); +INSERT INTO Books (title, price) VALUES ('The Catcher in the Rye', 11.20); \ No newline at end of file From 0e821cd0f37c0afbe819ed1f40b0427b4249c770 Mon Sep 17 00:00:00 2001 From: Nikolai Date: Mon, 9 Sep 2024 19:07:19 +0300 Subject: [PATCH 2/4] Added Ai suggested fixes --- src/main/java/mate/academy/Main.java | 4 +--- .../java/mate/academy/dao/BookDaoImpl.java | 19 +++++++++---------- src/main/java/mate/academy/model/Book.java | 6 ++++++ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java index 7c09dbea..f1cd929e 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -10,9 +10,7 @@ public class Main { public static void main(String[] args) { BookDao bookDao = (BookDao) injector.getInstance(BookDao.class); - Book book = new Book(); - book.setTitle("Java Programming"); - book.setPrice(new BigDecimal(200)); + Book book = new Book(1L, "Java Programming", new BigDecimal(200)); bookDao.create(book); bookDao.findAll().forEach(System.out::println); diff --git a/src/main/java/mate/academy/dao/BookDaoImpl.java b/src/main/java/mate/academy/dao/BookDaoImpl.java index 5c3d9115..dc7edadb 100644 --- a/src/main/java/mate/academy/dao/BookDaoImpl.java +++ b/src/main/java/mate/academy/dao/BookDaoImpl.java @@ -52,11 +52,7 @@ public Optional findById(Long id) { try (ResultSet resultSet = statement.executeQuery()) { if (resultSet.next()) { - Book book = new Book(); - book.setId(resultSet.getObject("id", Long.class)); - book.setPrice(resultSet.getObject("price", BigDecimal.class)); - book.setTitle(resultSet.getString("title")); - return Optional.of(book); + return Optional.of(getBook(resultSet)); } } } catch (SQLException e) { @@ -74,11 +70,7 @@ public List findAll() { ResultSet resultSet = statement.executeQuery()) { while (resultSet.next()) { - Book book = new Book(); - book.setId(resultSet.getObject("id", Long.class)); - book.setPrice(resultSet.getObject("price", BigDecimal.class)); - book.setTitle(resultSet.getString("title")); - books.add(book); + books.add(getBook(resultSet)); } } catch (SQLException e) { throw new DataProcessingException("Can't retrieve all books", e); @@ -113,4 +105,11 @@ public boolean deleteById(Long id) { throw new DataProcessingException("Can't delete book with id = " + id, e); } } + + private Book getBook(ResultSet resultSet) throws SQLException { + Long id = resultSet.getObject("id", Long.class); + BigDecimal price = resultSet.getObject("price", BigDecimal.class); + String title = resultSet.getString("title"); + return new Book(id, title, price); + } } diff --git a/src/main/java/mate/academy/model/Book.java b/src/main/java/mate/academy/model/Book.java index 6c956774..f4ace02d 100644 --- a/src/main/java/mate/academy/model/Book.java +++ b/src/main/java/mate/academy/model/Book.java @@ -7,6 +7,12 @@ public class Book { 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; } From 0908b61871fc3285629e2b0623892153e0eec55a Mon Sep 17 00:00:00 2001 From: Nikolai Date: Tue, 10 Sep 2024 11:55:20 +0300 Subject: [PATCH 3/4] Added bug fixes --- src/main/java/mate/academy/dao/BookDaoImpl.java | 13 +++++++++---- .../academy/exception/DataProcessingException.java | 4 ++++ src/main/resources/init_db.sql | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/mate/academy/dao/BookDaoImpl.java b/src/main/java/mate/academy/dao/BookDaoImpl.java index dc7edadb..cf40c08d 100644 --- a/src/main/java/mate/academy/dao/BookDaoImpl.java +++ b/src/main/java/mate/academy/dao/BookDaoImpl.java @@ -16,6 +16,7 @@ @Dao public class BookDaoImpl implements BookDao { + @Override public Book create(Book book) { String sql = "INSERT INTO books (title, price) VALUES (?, ?)"; @@ -26,15 +27,15 @@ public Book create(Book book) { int affectedRows = statement.executeUpdate(); - if (affectedRows == 0) { - throw new SQLException("Creating book failed, no rows affected."); + if (affectedRows < 1) { + throw new DataProcessingException("Creating book failed, no rows affected."); } try (ResultSet generatedKeys = statement.getGeneratedKeys()) { if (generatedKeys.next()) { - book.setId(generatedKeys.getLong(1)); + book.setId(generatedKeys.getObject(1, Long.class)); } else { - throw new SQLException("Creating book failed, no ID obtained."); + throw new DataProcessingException("Creating book failed, no ID obtained."); } } } catch (SQLException e) { @@ -44,6 +45,7 @@ public Book create(Book book) { return book; } + @Override public Optional findById(Long id) { String sql = "SELECT * FROM books WHERE id = ?"; @@ -62,6 +64,7 @@ public Optional findById(Long id) { return Optional.empty(); } + @Override public List findAll() { List books = new ArrayList<>(); String sql = "SELECT * FROM books"; @@ -79,6 +82,7 @@ public List findAll() { return books; } + @Override public Book update(Book book) { String sql = "UPDATE books SET price = ?, title = ? WHERE id = ?"; try (PreparedStatement statement = ConnectionUtil.getConnection().prepareStatement(sql)) { @@ -96,6 +100,7 @@ public Book update(Book book) { } } + @Override public boolean deleteById(Long id) { String sql = "DELETE FROM books WHERE id = ?"; try (PreparedStatement statement = ConnectionUtil.getConnection().prepareStatement(sql)) { diff --git a/src/main/java/mate/academy/exception/DataProcessingException.java b/src/main/java/mate/academy/exception/DataProcessingException.java index de9b45dc..02f156f9 100644 --- a/src/main/java/mate/academy/exception/DataProcessingException.java +++ b/src/main/java/mate/academy/exception/DataProcessingException.java @@ -4,4 +4,8 @@ public class DataProcessingException extends RuntimeException { public DataProcessingException(String message, Throwable ex) { super(message, ex); } + + public DataProcessingException(String message) { + super(message); + } } diff --git a/src/main/resources/init_db.sql b/src/main/resources/init_db.sql index 60beb762..8e515322 100644 --- a/src/main/resources/init_db.sql +++ b/src/main/resources/init_db.sql @@ -3,7 +3,7 @@ CREATE DATABASE IF NOT EXISTS BookStore DEFAULT CHARACTER SET utf8; USE BookStore; CREATE TABLE Books ( - id BIGINT NOT NULL AUTO_INCREMENT, + id BIGINT AUTO_INCREMENT, title VARCHAR(255) NOT NULL, price DECIMAL(10, 2) NOT NULL, PRIMARY KEY (id) From 8e6b870fd2203810b35443a30b21d551d784764d Mon Sep 17 00:00:00 2001 From: Nikolai Date: Tue, 10 Sep 2024 22:11:39 +0300 Subject: [PATCH 4/4] Removed redunant @Dao annotation --- src/main/java/mate/academy/dao/BookDao.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/mate/academy/dao/BookDao.java b/src/main/java/mate/academy/dao/BookDao.java index 54263faf..d60c063d 100644 --- a/src/main/java/mate/academy/dao/BookDao.java +++ b/src/main/java/mate/academy/dao/BookDao.java @@ -2,10 +2,8 @@ import java.util.List; import java.util.Optional; -import mate.academy.lib.Dao; import mate.academy.model.Book; -@Dao public interface BookDao { Book create(Book book);