diff --git a/pom.xml b/pom.xml index 683e84ec..ee12ea36 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,14 @@ + + + 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..0684324f 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -1,7 +1,30 @@ 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"); + private static final BookDao bookDao = (BookDao) injector.getInstance(BookDao.class); + public static void main(String[] args) { + Book book1 = new Book(); + book1.setTitle("SQL for Data Analysis"); + book1.setPrice(BigDecimal.valueOf(500)); + book1 = bookDao.create(book1); + Book book2 = new Book(); + book2.setTitle("Effective Java"); + book2.setPrice(BigDecimal.valueOf(800)); + book2 = bookDao.create(book2); + System.out.println(bookDao.findById(book2.getId())); + System.out.println(bookDao.getAll()); + System.out.println(bookDao.delete(book1.getId())); + book2.setTitle("Joshua Bloch: Effective Java"); + book2.setPrice(BigDecimal.valueOf(850)); + bookDao.update(book2); + System.out.println(bookDao.getAll()); } } 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..9c521496 --- /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 getAll(); + + Book update(Book book); + + boolean delete(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..16a37406 --- /dev/null +++ b/src/main/java/mate/academy/dao/BookDaoImpl.java @@ -0,0 +1,129 @@ +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.exceptions.DataProcessingException; +import mate.academy.lib.Dao; +import mate.academy.model.Book; +import mate.academy.utils.ConnectionUtil; + +@Dao +public class BookDaoImpl implements BookDao { + @Override + public Book create(Book book) { + String insertBookQuery = "INSERT INTO books (title, price) VALUES (?, ?);"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection + .prepareStatement(insertBookQuery, Statement.RETURN_GENERATED_KEYS)) { + statement.setString(1, book.getTitle()); + statement.setBigDecimal(2, book.getPrice()); + int affectedRows = statement.executeUpdate(); + if (affectedRows < 1) { + throw new DataProcessingException("Excepted to insert at least one row, " + + "but inserted 0 rows", + new RuntimeException()); + } + 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 with title: " + + book.getTitle() + + ", and price: " + + book.getPrice() + ":", e); + } + return book; + } + + @Override + public Optional findById(Long id) { + String findBookQuery = "SELECT * from books WHERE id = ? AND is_deleted = FALSE;"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection + .prepareStatement(findBookQuery)) { + statement.setLong(1, id); + ResultSet resultSet = statement.executeQuery(); + Book book = null; + if (resultSet.next()) { + book = getBookFromResultSet(resultSet); + } + return Optional.ofNullable(book); + } catch (SQLException e) { + throw new DataProcessingException("Can't find book from id " + id + ":", e); + } + } + + @Override + public List getAll() { + List books = new ArrayList<>(); + String getAllBookQuery = "SELECT * FROM books WHERE is_deleted = FALSE;"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection + .prepareStatement(getAllBookQuery)) { + ResultSet resultSet = statement.executeQuery(); + while (resultSet.next()) { + books.add(getBookFromResultSet(resultSet)); + } + } catch (SQLException e) { + throw new DataProcessingException("Can't get all books from DB:", e); + } + return books; + } + + @Override + public Book update(Book book) { + String updateBookQuery = + "UPDATE books SET title = ?, price = ? WHERE id = ? AND is_deleted = FALSE;"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection + .prepareStatement(updateBookQuery)) { + 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("Excepted to update at least one row, " + + "but updated 0 rows:", + new RuntimeException()); + } + } catch (SQLException e) { + throw new DataProcessingException("Can't update book by id:" + book.getId(), e); + } + return book; + } + + @Override + public boolean delete(Long id) { + String deleteBookQuery = "UPDATE books SET is_deleted = TRUE WHERE id = ?;"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection + .prepareStatement(deleteBookQuery)) { + statement.setLong(1, id); + int affectedRows = statement.executeUpdate(); + return affectedRows > 0; + } catch (SQLException e) { + throw new DataProcessingException("Can't delete book by 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"); + Book book = new Book(); + book.setId(id); + book.setTitle(title); + book.setPrice(price); + return book; + } +} 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/model/Book.java b/src/main/java/mate/academy/model/Book.java new file mode 100644 index 00000000..e2cb4289 --- /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 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/resources/init_db.sql b/src/main/java/mate/academy/resources/init_db.sql new file mode 100644 index 00000000..cf50286c --- /dev/null +++ b/src/main/java/mate/academy/resources/init_db.sql @@ -0,0 +1,9 @@ +CREATE TABLE `books` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `title` varchar(45) DEFAULT NULL, + `price` decimal(10,2) DEFAULT NULL, + `is_deleted` bit(1) NOT NULL DEFAULT b'0', + PRIMARY KEY (`id`), + UNIQUE KEY `id_UNIQUE` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + diff --git a/src/main/java/mate/academy/utils/ConnectionUtil.java b/src/main/java/mate/academy/utils/ConnectionUtil.java new file mode 100644 index 00000000..0b83a4fe --- /dev/null +++ b/src/main/java/mate/academy/utils/ConnectionUtil.java @@ -0,0 +1,29 @@ +package mate.academy.utils; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; + +public class ConnectionUtil { + private static final String USERNAME = "root"; + private static final String PASSWORD = "12345678"; + private static final String DB_URL = "jdbc:mysql://localhost:3306/library"; + private static final String DRIVER_PACKAGE = "com.mysql.cj.jdbc.Driver"; + private static final Properties DB_PROPERTIES; + + static { + DB_PROPERTIES = new Properties(); + DB_PROPERTIES.put("user", USERNAME); + DB_PROPERTIES.put("password", PASSWORD); + try { + Class.forName(DRIVER_PACKAGE); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Can not load JDBC driver :" + e); + } + } + + public static Connection getConnection() throws SQLException { + return DriverManager.getConnection(DB_URL, DB_PROPERTIES); + } +}