From 50d35674badd4e015771b428ce366f854d91ab03 Mon Sep 17 00:00:00 2001 From: Oleksii Date: Sun, 7 Jul 2024 20:46:11 +0300 Subject: [PATCH 1/3] first commit --- pom.xml | 8 ++ .../java/mate/academy/ConnectionUtil.java | 27 ++++ src/main/java/mate/academy/Main.java | 17 +++ src/main/java/mate/academy/dao/BookDao.java | 17 +++ .../java/mate/academy/dao/BookDaoImpl.java | 126 ++++++++++++++++++ .../exception/DataProcessingException.java | 6 + src/main/java/mate/academy/model/Book.java | 42 ++++++ src/main/resources/init_db.sql | 6 + 8 files changed, 249 insertions(+) create mode 100644 src/main/java/mate/academy/ConnectionUtil.java 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/resources/init_db.sql diff --git a/pom.xml b/pom.xml index 683e84ec..65d0b474 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,14 @@ + + + com.mysql + mysql-connector-j + 9.0.0 + + + diff --git a/src/main/java/mate/academy/ConnectionUtil.java b/src/main/java/mate/academy/ConnectionUtil.java new file mode 100644 index 00000000..9a3e29d0 --- /dev/null +++ b/src/main/java/mate/academy/ConnectionUtil.java @@ -0,0 +1,27 @@ +package mate.academy; + +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/test"; + private static final Properties DB_PROPERTIES; + + static { + DB_PROPERTIES = new Properties(); + DB_PROPERTIES.put("user", "root"); + DB_PROPERTIES.put("password", "v1f9v7f7"); + + try { + Class.forName("com.mysql.cj.jdbc.Driver"); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Could not load MySQL driver", e); + } + } + + public static Connection getConnection() throws SQLException { + return DriverManager.getConnection(DB_URL, DB_PROPERTIES); + } +} diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java index 0058fbf9..4fea9abe 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -1,7 +1,24 @@ 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("99.99")); + System.out.println(bookDao.create(book)); + System.out.println(bookDao.findById(4L)); + System.out.println(bookDao.findAll()); + System.out.println(bookDao.update(book)); + System.out.println(bookDao.deleteById(4L)); } } 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/BookDaoImpl.java b/src/main/java/mate/academy/dao/BookDaoImpl.java new file mode 100644 index 00000000..4a443e85 --- /dev/null +++ b/src/main/java/mate/academy/dao/BookDaoImpl.java @@ -0,0 +1,126 @@ +package mate.academy.dao; + +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.ConnectionUtil; +import mate.academy.exception.DataProcessingException; +import mate.academy.lib.Dao; +import mate.academy.model.Book; + +@Dao +public class BookDaoImpl implements BookDao { + + @Override + public Book create(Book book) { + String query = "INSERT INTO book (title, price) VALUES (?, ?);"; + + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement( + query, Statement.RETURN_GENERATED_KEYS)) { + preparedStatement.setString(1, book.getTitle()); + preparedStatement.setBigDecimal(2, book.getPrice()); + int affectRows = preparedStatement.executeUpdate(); + if (affectRows == 0) { + throw new DataProcessingException( + "Expected to add at least one row but added 0", + new SQLException()); + } + ResultSet generatedKeys = preparedStatement.getGeneratedKeys(); + if (generatedKeys.next()) { + Long id = generatedKeys.getObject(1, Long.class); + book.setId(id); + } + } catch (SQLException e) { + throw new DataProcessingException("Failed to create book " + book, e); + } + return book; + } + + @Override + public Optional findById(Long id) { + String query = "SELECT * FROM book WHERE id = ?;"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement(query)) { + preparedStatement.setLong(1, id); + ResultSet resultSet = preparedStatement.executeQuery(); + if (resultSet.next()) { + return Optional.of(creatingBook(resultSet, id)); + } + } catch (SQLException e) { + throw new DataProcessingException("Failed to find book by id: " + id, e); + } + return Optional.empty(); + } + + @Override + public List findAll() { + String query = "SELECT * FROM book;"; + List books = new ArrayList<>(); + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement(query)) { + ResultSet resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + Long id = resultSet.getObject("id", Long.class); + books.add(creatingBook(resultSet, id)); + return books; + } + } catch (SQLException e) { + throw new DataProcessingException("Failed to find books", e); + } + return new ArrayList<>(); + } + + @Override + public Book update(Book book) { + String query = "UPDATE book SET title = ?, price = ? WHERE id = ?;"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement( + query, Statement.RETURN_GENERATED_KEYS)) { + preparedStatement.setString(1, book.getTitle()); + preparedStatement.setBigDecimal(2, book.getPrice()); + preparedStatement.setLong(3, book.getId()); + int affectRows = preparedStatement.executeUpdate(); + if (affectRows == 0) { + throw new DataProcessingException( + "Expected to update at least one row but updated 0", + new SQLException()); + } + } catch (SQLException e) { + throw new DataProcessingException("Failed to update book " + book, e); + } + return book; + } + + @Override + public boolean deleteById(Long id) { + String query = "DELETE FROM book WHERE id = ?;"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement preparedStatement = connection.prepareStatement(query)) { + preparedStatement.setLong(1, id); + return preparedStatement.executeUpdate() > 0; + } catch (SQLException e) { + throw new DataProcessingException("Can't delete an object with id: " + id, e); + } + } + + private Book creatingBook(ResultSet resultSet, Long id) { + try { + String title = resultSet.getString("title"); + BigDecimal price = resultSet.getObject("price", BigDecimal.class); + Book book = new Book(); + book.setId(id); + book.setTitle(title); + book.setPrice(price); + return book; + } catch (SQLException e) { + throw new DataProcessingException("Can't create a 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..54144c18 --- /dev/null +++ b/src/main/java/mate/academy/exception/DataProcessingException.java @@ -0,0 +1,6 @@ +package mate.academy.exception; + +public class DataProcessingException extends RuntimeException { + public DataProcessingException(String message, Throwable 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..e06a8e98 --- /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 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; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Override + public String toString() { + return "Book{" + + "id=" + id + + ", title='" + title + '\'' + + ", price=" + price + + '}'; + } +} diff --git a/src/main/resources/init_db.sql b/src/main/resources/init_db.sql new file mode 100644 index 00000000..ca042329 --- /dev/null +++ b/src/main/resources/init_db.sql @@ -0,0 +1,6 @@ +USE test; +CREATE TABLE book ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + title VARCHAR(255), + price DECIMAL(10, 2) +); \ No newline at end of file From 0a44e1fe40797fb2189632c0153089d4a9e8484e Mon Sep 17 00:00:00 2001 From: Oleksii Date: Sun, 7 Jul 2024 22:15:53 +0300 Subject: [PATCH 2/3] refactor after Olena Bruyako's review --- src/main/java/mate/academy/Main.java | 4 ++-- src/main/java/mate/academy/dao/BookDaoImpl.java | 12 +++++------- .../java/mate/academy/{ => util}/ConnectionUtil.java | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) rename src/main/java/mate/academy/{ => util}/ConnectionUtil.java (96%) diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java index 4fea9abe..f5cd923b 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -16,9 +16,9 @@ public static void main(String[] args) { book.setPrice(new BigDecimal("99.99")); System.out.println(bookDao.create(book)); - System.out.println(bookDao.findById(4L)); + System.out.println(bookDao.findById(1L)); System.out.println(bookDao.findAll()); System.out.println(bookDao.update(book)); - System.out.println(bookDao.deleteById(4L)); + System.out.println(bookDao.deleteById(1L)); } } diff --git a/src/main/java/mate/academy/dao/BookDaoImpl.java b/src/main/java/mate/academy/dao/BookDaoImpl.java index 4a443e85..810494f8 100644 --- a/src/main/java/mate/academy/dao/BookDaoImpl.java +++ b/src/main/java/mate/academy/dao/BookDaoImpl.java @@ -9,14 +9,13 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import mate.academy.ConnectionUtil; 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 { - @Override public Book create(Book book) { String query = "INSERT INTO book (title, price) VALUES (?, ?);"; @@ -51,7 +50,7 @@ public Optional findById(Long id) { preparedStatement.setLong(1, id); ResultSet resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { - return Optional.of(creatingBook(resultSet, id)); + return Optional.of(mapResultSetToBook(resultSet, id)); } } catch (SQLException e) { throw new DataProcessingException("Failed to find book by id: " + id, e); @@ -68,13 +67,12 @@ public List findAll() { ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { Long id = resultSet.getObject("id", Long.class); - books.add(creatingBook(resultSet, id)); - return books; + books.add(mapResultSetToBook(resultSet, id)); } } catch (SQLException e) { throw new DataProcessingException("Failed to find books", e); } - return new ArrayList<>(); + return books; } @Override @@ -110,7 +108,7 @@ public boolean deleteById(Long id) { } } - private Book creatingBook(ResultSet resultSet, Long id) { + private Book mapResultSetToBook(ResultSet resultSet, Long id) { try { String title = resultSet.getString("title"); BigDecimal price = resultSet.getObject("price", BigDecimal.class); diff --git a/src/main/java/mate/academy/ConnectionUtil.java b/src/main/java/mate/academy/util/ConnectionUtil.java similarity index 96% rename from src/main/java/mate/academy/ConnectionUtil.java rename to src/main/java/mate/academy/util/ConnectionUtil.java index 9a3e29d0..f194f017 100644 --- a/src/main/java/mate/academy/ConnectionUtil.java +++ b/src/main/java/mate/academy/util/ConnectionUtil.java @@ -1,4 +1,4 @@ -package mate.academy; +package mate.academy.util; import java.sql.Connection; import java.sql.DriverManager; From aeffd9a1c73eb3437654ca44d62fec49d8bdc9f0 Mon Sep 17 00:00:00 2001 From: Oleksii Date: Mon, 8 Jul 2024 09:17:28 +0300 Subject: [PATCH 3/3] Update ConnectionUtil.java --- src/main/java/mate/academy/util/ConnectionUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mate/academy/util/ConnectionUtil.java b/src/main/java/mate/academy/util/ConnectionUtil.java index f194f017..944955ff 100644 --- a/src/main/java/mate/academy/util/ConnectionUtil.java +++ b/src/main/java/mate/academy/util/ConnectionUtil.java @@ -12,7 +12,7 @@ public class ConnectionUtil { static { DB_PROPERTIES = new Properties(); DB_PROPERTIES.put("user", "root"); - DB_PROPERTIES.put("password", "v1f9v7f7"); + DB_PROPERTIES.put("password", "********"); try { Class.forName("com.mysql.cj.jdbc.Driver");