From c039e8d7cb1524323fd156682bf97a2803b36e66 Mon Sep 17 00:00:00 2001 From: Oleksandr Prots Date: Wed, 2 Oct 2024 21:55:40 +0300 Subject: [PATCH 1/4] jv-jdbc-intro --- pom.xml | 8 ++ src/main/java/mate/academy/Main.java | 43 ++++++ src/main/java/mate/academy/dao/BookDao.java | 20 +++ .../java/mate/academy/{lib => dao}/Dao.java | 2 +- .../mate/academy/dao/impl/BookDaoImpl.java | 128 ++++++++++++++++++ .../exceptions/DataProcessingException.java | 7 + .../java/mate/academy/lib/ConnectionUtil.java | 29 ++++ src/main/java/mate/academy/lib/Injector.java | 1 + src/main/java/mate/academy/model/Book.java | 62 +++++++++ src/main/resources/init_db.sql | 5 + 10 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 src/main/java/mate/academy/dao/BookDao.java rename src/main/java/mate/academy/{lib => dao}/Dao.java (85%) 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/lib/ConnectionUtil.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..f8c07312 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,14 @@ https://raw.githubusercontent.com/mate-academy/style-guides/master/java/checkstyle.xml + + + mysql + mysql-connector-java + 8.0.33 + + @@ -54,5 +61,6 @@ + diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java index 0058fbf9..1bf93f04 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -1,7 +1,50 @@ package mate.academy; +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; +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); + + Optional foundBook = bookDao.findById(1L); + if (foundBook.isPresent()) { + System.out.println("Book found: " + foundBook.get()); + } else { + System.out.println("Book not found"); + } + Book book = new Book(); + book.setId(1L); + book.setPrice(new BigDecimal("100.00")); + book.setTitle("Alice"); + bookDao.create(book); + System.out.println("Book created: " + book); + + if (foundBook.isPresent()) { + Book bookToUpdate = foundBook.get(); + bookToUpdate.setTitle("Alice in Wonderland"); + bookToUpdate.setPrice(new BigDecimal("120.00")); + bookDao.update(bookToUpdate); + System.out.println("Book updated: " + bookToUpdate); + } + + List allBooks = bookDao.findAll(); + System.out.println("All books in the database:"); + for (Book b : allBooks) { + System.out.println(b); + } + boolean isDeleted = bookDao.deleteById(1L); + if (isDeleted) { + System.out.println("Book with ID 1 deleted."); + } else { + System.out.println("Book with ID 1 not found."); + } } } 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..83ffa53c --- /dev/null +++ b/src/main/java/mate/academy/dao/BookDao.java @@ -0,0 +1,20 @@ +package mate.academy.dao; + +import java.util.List; +import java.util.Optional; +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/lib/Dao.java b/src/main/java/mate/academy/dao/Dao.java similarity index 85% rename from src/main/java/mate/academy/lib/Dao.java rename to src/main/java/mate/academy/dao/Dao.java index f558d09a..7b4fe135 100644 --- a/src/main/java/mate/academy/lib/Dao.java +++ b/src/main/java/mate/academy/dao/Dao.java @@ -1,4 +1,4 @@ -package mate.academy.lib; +package mate.academy.dao; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; 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..d181c4f9 --- /dev/null +++ b/src/main/java/mate/academy/dao/impl/BookDaoImpl.java @@ -0,0 +1,128 @@ +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.dao.Dao; +import mate.academy.exceptions.DataProcessingException; +import mate.academy.lib.ConnectionUtil; +import mate.academy.model.Book; + +@Dao +public class BookDaoImpl implements BookDao { + + @Override + public Book create(Book book) { + String sql = "INSERT INTO books (title, price) VALUES (?, ?)"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection.prepareStatement( + sql, Statement.RETURN_GENERATED_KEYS)) { + statement.setString(1, book.getTitle()); + statement.setBigDecimal(2, book.getPrice()); + if (statement.executeUpdate() < 1) { + throw new RuntimeException("Expected to insert 1 record but inserted 0 rows"); + } + ResultSet generatedKeys = statement.getGeneratedKeys(); + if (generatedKeys.next()) { + Long id = generatedKeys.getObject(1, Long.class); + book.setId(id); + } + } catch (SQLException e) { + throw new DataProcessingException("Can't create book",e); + } + return book; + } + + @Override + public Optional findById(Long id) { + String sql = "SELECT * FROM books WHERE id = ?"; + if (id == null) { + return Optional.empty(); + } + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setLong(1, id); + ResultSet resultSet = statement.executeQuery(); + if (resultSet.next()) { + String title = resultSet.getObject("title", String.class); + BigDecimal price = resultSet.getObject("price", BigDecimal.class); + + Book book = new Book(); + book.setId(id); + book.setPrice(price); + book.setTitle(title); + return Optional.of(book); + } + return Optional.empty(); + } catch (SQLException e) { + throw new DataProcessingException("Can't find book from DB",e); + } + } + + @Override + public List findAll() { + String sql = "SELECT * FROM books"; + List books = new ArrayList<>(); + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql)) { + ResultSet resultSet = statement.executeQuery(); + while (resultSet.next()) { + Long id = resultSet.getObject("id", Long.class); + String title = resultSet.getObject("title", String.class); + BigDecimal price = resultSet.getObject("price", BigDecimal.class); + + Book book = new Book(); + book.setId(id); + book.setPrice(price); + book.setTitle(title); + books.add(book); + } + } catch (SQLException e) { + throw new DataProcessingException("Can't find books from DB",e); + } + return books; + } + + @Override + public Book update(Book book) { + String sql = "UPDATE books SET title = ?, price = ? WHERE id = ?"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql, + Statement.RETURN_GENERATED_KEYS)) { + statement.setString(1, book.getTitle()); + statement.setBigDecimal(2, book.getPrice()); + statement.setLong(3, book.getId()); + if (statement.executeUpdate() < 1) { + throw new RuntimeException("Expected to insert 1 record but inserted 0 rows"); + } + return book; + } catch (SQLException e) { + throw new DataProcessingException("Can't update book from DB",e); + } + } + + @Override + public boolean deleteById(Long id) { + if (id == null) { + return false; + } + String sql = "DELETE FROM books WHERE id = ?"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setLong(1, id); + if (statement.executeUpdate() < 1) { + return false; + } + } catch (SQLException e) { + throw new DataProcessingException("Can't delete book from DB",e); + } + return true; + } +} 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..798fcffc --- /dev/null +++ b/src/main/java/mate/academy/exceptions/DataProcessingException.java @@ -0,0 +1,7 @@ +package mate.academy.exceptions; + +public class DataProcessingException extends RuntimeException { + public DataProcessingException(String message, Throwable ex) { + super(message, ex); + } +} diff --git a/src/main/java/mate/academy/lib/ConnectionUtil.java b/src/main/java/mate/academy/lib/ConnectionUtil.java new file mode 100644 index 00000000..a74d68cc --- /dev/null +++ b/src/main/java/mate/academy/lib/ConnectionUtil.java @@ -0,0 +1,29 @@ +package mate.academy.lib; + +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 String USER = "root"; + private static final String PASSWORD = "qwerty123"; + private static final Properties DB_PROPERTIES; + + static { + DB_PROPERTIES = new Properties(); + DB_PROPERTIES.put("user", USER); + DB_PROPERTIES.put("password", PASSWORD); + try { + Class.forName("com.mysql.cj.jdbc.Driver"); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Can not load JDBC driver", e); + } + } + + public static Connection getConnection() throws SQLException { + return DriverManager.getConnection(DB_URL); + } +} diff --git a/src/main/java/mate/academy/lib/Injector.java b/src/main/java/mate/academy/lib/Injector.java index ea13c49e..ad8d133d 100644 --- a/src/main/java/mate/academy/lib/Injector.java +++ b/src/main/java/mate/academy/lib/Injector.java @@ -9,6 +9,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import mate.academy.dao.Dao; public class Injector { private static final Map injectors = new HashMap<>(); 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..7ddf12bb --- /dev/null +++ b/src/main/java/mate/academy/model/Book.java @@ -0,0 +1,62 @@ +package mate.academy.model; + +import java.math.BigDecimal; +import java.util.Objects; + +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 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 boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Book book = (Book) o; + return Objects.equals(id, book.id) + && Objects.equals(title, book.title) + && Objects.equals(price, book.price); + } + + @Override + public int hashCode() { + return Objects.hash(id, title, price); + } + + @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..c69c7c8e --- /dev/null +++ b/src/main/resources/init_db.sql @@ -0,0 +1,5 @@ +CREATE TABLE books { + id INT PRIMARY KEY AUTO_INCREMENT, + title VARCHAR(255) NOT NULL, + price DECIMAL (10, 2) NOT NULL + } \ No newline at end of file From 85ce6a112ef73f6c7cfde69bfbc9af1f04f15ce3 Mon Sep 17 00:00:00 2001 From: Oleksandr Prots Date: Wed, 2 Oct 2024 22:03:03 +0300 Subject: [PATCH 2/4] jv-jdbc-intro --- src/main/java/mate/academy/Main.java | 63 +++++++++---------- .../mate/academy/dao/impl/BookDaoImpl.java | 10 +-- 2 files changed, 34 insertions(+), 39 deletions(-) diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java index 1bf93f04..b6122985 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -10,41 +10,36 @@ 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); + public static void main(String[] args) { + BookDao bookDao = (BookDao) INJECTOR.getInstance(BookDao.class); + Optional foundBook = bookDao.findById(1L); + if (foundBook.isPresent()) { + System.out.println("Book found: " + foundBook.get()); + Book bookToUpdate = foundBook.get(); + bookToUpdate.setTitle("Alice in Wonderland"); + bookToUpdate.setPrice(new BigDecimal("120.00")); + bookDao.update(bookToUpdate); + System.out.println("Book updated: " + bookToUpdate); + } else { + System.out.println("Book not found. Creating a new book."); + Book book = new Book(); + book.setPrice(new BigDecimal("100.00")); + book.setTitle("Alice"); + bookDao.create(book); + System.out.println("Book created: " + book); + } - Optional foundBook = bookDao.findById(1L); - if (foundBook.isPresent()) { - System.out.println("Book found: " + foundBook.get()); - } else { - System.out.println("Book not found"); - } - Book book = new Book(); - book.setId(1L); - book.setPrice(new BigDecimal("100.00")); - book.setTitle("Alice"); - bookDao.create(book); - System.out.println("Book created: " + book); - - if (foundBook.isPresent()) { - Book bookToUpdate = foundBook.get(); - bookToUpdate.setTitle("Alice in Wonderland"); - bookToUpdate.setPrice(new BigDecimal("120.00")); - bookDao.update(bookToUpdate); - System.out.println("Book updated: " + bookToUpdate); - } - - List allBooks = bookDao.findAll(); - System.out.println("All books in the database:"); - for (Book b : allBooks) { - System.out.println(b); - } + List allBooks = bookDao.findAll(); + System.out.println("All books in the database:"); + for (Book b : allBooks) { + System.out.println(b); + } - boolean isDeleted = bookDao.deleteById(1L); - if (isDeleted) { - System.out.println("Book with ID 1 deleted."); - } else { - System.out.println("Book with ID 1 not found."); + boolean isDeleted = bookDao.deleteById(1L); + if (isDeleted) { + System.out.println("Book with ID 1 deleted."); + } else { + System.out.println("Book with ID 1 not found."); + } } } -} diff --git a/src/main/java/mate/academy/dao/impl/BookDaoImpl.java b/src/main/java/mate/academy/dao/impl/BookDaoImpl.java index d181c4f9..006220cb 100644 --- a/src/main/java/mate/academy/dao/impl/BookDaoImpl.java +++ b/src/main/java/mate/academy/dao/impl/BookDaoImpl.java @@ -35,7 +35,7 @@ public Book create(Book book) { book.setId(id); } } catch (SQLException e) { - throw new DataProcessingException("Can't create book",e); + throw new DataProcessingException("Can't create book: " + book, e); } return book; } @@ -62,7 +62,7 @@ public Optional findById(Long id) { } return Optional.empty(); } catch (SQLException e) { - throw new DataProcessingException("Can't find book from DB",e); + throw new DataProcessingException("Can't get book by id" + id, e); } } @@ -85,7 +85,7 @@ public List findAll() { books.add(book); } } catch (SQLException e) { - throw new DataProcessingException("Can't find books from DB",e); + throw new DataProcessingException("Can't find all books", e); } return books; } @@ -104,7 +104,7 @@ public Book update(Book book) { } return book; } catch (SQLException e) { - throw new DataProcessingException("Can't update book from DB",e); + throw new DataProcessingException("Can't update book " + book, e); } } @@ -121,7 +121,7 @@ public boolean deleteById(Long id) { return false; } } catch (SQLException e) { - throw new DataProcessingException("Can't delete book from DB",e); + throw new DataProcessingException("Can't delete book by id " + id, e); } return true; } From 9df48bc2cb86f51d5a7565dcf4adb4915e2e5d5a Mon Sep 17 00:00:00 2001 From: Oleksandr Prots Date: Mon, 7 Oct 2024 17:11:38 +0300 Subject: [PATCH 3/4] jv-jdbc-intro --- src/main/java/mate/academy/Main.java | 60 ++++++++++++++-------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java index b6122985..1cb7051b 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -10,36 +10,34 @@ 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); - Optional foundBook = bookDao.findById(1L); - if (foundBook.isPresent()) { - System.out.println("Book found: " + foundBook.get()); - Book bookToUpdate = foundBook.get(); - bookToUpdate.setTitle("Alice in Wonderland"); - bookToUpdate.setPrice(new BigDecimal("120.00")); - bookDao.update(bookToUpdate); - System.out.println("Book updated: " + bookToUpdate); - } else { - System.out.println("Book not found. Creating a new book."); - Book book = new Book(); - book.setPrice(new BigDecimal("100.00")); - book.setTitle("Alice"); - bookDao.create(book); - System.out.println("Book created: " + book); - } - - List allBooks = bookDao.findAll(); - System.out.println("All books in the database:"); - for (Book b : allBooks) { - System.out.println(b); - } - - boolean isDeleted = bookDao.deleteById(1L); - if (isDeleted) { - System.out.println("Book with ID 1 deleted."); - } else { - System.out.println("Book with ID 1 not found."); - } + public static void main(String[] args) { + BookDao bookDao = (BookDao) INJECTOR.getInstance(BookDao.class); + Optional foundBook = bookDao.findById(1L); + if (foundBook.isPresent()) { + System.out.println("Book found: " + foundBook.get()); + Book bookToUpdate = foundBook.get(); + bookToUpdate.setTitle("Alice in Wonderland"); + bookToUpdate.setPrice(new BigDecimal("120.00")); + bookDao.update(bookToUpdate); + System.out.println("Book updated: " + bookToUpdate); + } else { + System.out.println("Book not found. Creating a new book."); + Book book = new Book(); + book.setPrice(new BigDecimal("100.00")); + book.setTitle("Alice"); + bookDao.create(book); + System.out.println("Book created: " + book); + } + List allBooks = bookDao.findAll(); + System.out.println("All books in the database:"); + for (Book b : allBooks) { + System.out.println(b); + } + boolean isDeleted = bookDao.deleteById(1L); + if (isDeleted) { + System.out.println("Book with ID 1 deleted."); + } else { + System.out.println("Book with ID 1 not found."); } } +} From 8efe7857dd893058905e37fbc2500543bd480d91 Mon Sep 17 00:00:00 2001 From: Oleksandr Prots Date: Mon, 7 Oct 2024 17:15:04 +0300 Subject: [PATCH 4/4] jv-jdbc-intro --- src/main/java/mate/academy/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java index 1cb7051b..caf111dd 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -14,7 +14,7 @@ public static void main(String[] args) { BookDao bookDao = (BookDao) INJECTOR.getInstance(BookDao.class); Optional foundBook = bookDao.findById(1L); if (foundBook.isPresent()) { - System.out.println("Book found: " + foundBook.get()); + System.out.println("Book found:" + foundBook.get()); Book bookToUpdate = foundBook.get(); bookToUpdate.setTitle("Alice in Wonderland"); bookToUpdate.setPrice(new BigDecimal("120.00"));