diff --git a/pom.xml b/pom.xml index 683e84ec..fc0fcfa1 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,14 @@ + + + mysql + mysql-connector-java + 8.0.28 + + + diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java index 0058fbf9..fe717f89 100644 --- a/src/main/java/mate/academy/Main.java +++ b/src/main/java/mate/academy/Main.java @@ -1,7 +1,34 @@ 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); + + Book book = new Book("book", BigDecimal.valueOf(100)); + Book createdBook = bookDao.create(book); + System.out.println(createdBook); + + Optional getBookById = bookDao.findById(1L); + System.out.println("Book by id " + getBookById); + + book.setTitle("Updated Book"); + book.setPrice(BigDecimal.valueOf(200)); + Book updatedBook = bookDao.update(book); + System.out.println("Updated Book: " + updatedBook); + + List getAllBook = bookDao.findAll(); + System.out.println("All Books : " + getAllBook); + boolean deleteBook = bookDao.deleteById(3L); + System.out.println("Deleted book: " + deleteBook); } } 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..dd79bf86 --- /dev/null +++ b/src/main/java/mate/academy/dao/impl/BookDaoImpl.java @@ -0,0 +1,121 @@ +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.exception.DataProcessingException; +import mate.academy.lib.Dao; +import mate.academy.model.Book; +import mate.academy.util.db.ConnectionUtil; + +@Dao +public class BookDaoImpl implements BookDao { + private static final String CANT_CREATE = "Can't store the book to the DB"; + private static final String CANT_FIND_BY_ID = "Can't find the book with id = "; + private static final String CANT_FIND_ALL = "Can't find all books"; + private static final String CANT_UPDATE = "Can't update the book with id = "; + private static final String CANT_DELETE = "Can't delete the book with id = "; + private static final String UPDATE_FAILED + = "Expected to update at least 1 row, but 0 was updated."; + private static final String INSERT_FAILED + = "Expected to update at least 1 row, but 0 was updated."; + + @Override + public Book create(Book book) { + String insertQuery = "INSERT INTO books (title,price) VALUES (?,?);"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection.prepareStatement( + insertQuery, Statement.RETURN_GENERATED_KEYS)) { + statement.setString(1, book.getTitle()); + statement.setBigDecimal(2, book.getPrice()); + statement.executeUpdate(); + ResultSet generatedKey = statement.getGeneratedKeys(); + if (generatedKey.next()) { + Long id = generatedKey.getObject(1, Long.class); + book.setId(id); + } else { + throw new DataProcessingException(INSERT_FAILED); + } + } catch (SQLException e) { + throw new DataProcessingException(CANT_CREATE, e); + } + return book; + } + + @Override + public Optional findById(Long id) { + String getByIdQuery = "SELECT * FROM books WHERE id = ? AND is_deleted = FALSE"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection.prepareStatement(getByIdQuery)) { + statement.setLong(1, id); + ResultSet resultSet = statement.executeQuery(); + if (resultSet.next()) { + return Optional.of(createBook(resultSet)); + } + } catch (SQLException e) { + throw new DataProcessingException(CANT_FIND_BY_ID + id, e); + } + return Optional.empty(); + } + + @Override + public List findAll() { + String getAllQuery = "SELECT * FROM books WHERE is_deleted = FALSE"; + List books = new ArrayList<>(); + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection.prepareStatement(getAllQuery)) { + ResultSet resultSet = statement.executeQuery(); + while (resultSet.next()) { + books.add(createBook(resultSet)); + } + } catch (SQLException e) { + throw new DataProcessingException(CANT_FIND_ALL, e); + } + return books; + } + + @Override + public Book update(Book book) { + String updateQuery = "UPDATE books SET title = ?, price = ? " + + "WHERE id = ? AND is_deleted = FALSE"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection.prepareStatement(updateQuery)) { + 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(UPDATE_FAILED); + } + } catch (SQLException e) { + throw new DataProcessingException(CANT_UPDATE + book.getId(), e); + } + return book; + } + + @Override + public boolean deleteById(Long id) { + String deletedQuery = "UPDATE books SET is_deleted = TRUE WHERE id = ?"; + try (Connection connection = ConnectionUtil.getConnection(); + PreparedStatement statement = connection.prepareStatement(deletedQuery)) { + statement.setLong(1, id); + return statement.executeUpdate() > 0; + } catch (SQLException e) { + throw new DataProcessingException(CANT_DELETE + id, e); + } + } + + private Book createBook(ResultSet resultSet) throws SQLException { + return new Book( + resultSet.getObject("id", Long.class), + resultSet.getObject("title", String.class), + resultSet.getObject("price", BigDecimal.class)); + } +} 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..65af6fdf --- /dev/null +++ b/src/main/java/mate/academy/exception/DataProcessingException.java @@ -0,0 +1,11 @@ +package mate.academy.exception; + +public class DataProcessingException extends RuntimeException { + public DataProcessingException(String message) { + super(message); + } + + public DataProcessingException(String message, Throwable exception) { + super(message, exception); + } +} 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..2e2e75c8 --- /dev/null +++ b/src/main/java/mate/academy/model/Book.java @@ -0,0 +1,53 @@ +package mate.academy.model; + +import java.math.BigDecimal; + +public class Book { + private Long id; + private String title; + private BigDecimal price; + + public Book() { + } + + public Book(String title, BigDecimal price) { + this.title = title; + this.price = 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/db/ConnectionUtil.java b/src/main/java/mate/academy/util/db/ConnectionUtil.java new file mode 100644 index 00000000..dd4d91be --- /dev/null +++ b/src/main/java/mate/academy/util/db/ConnectionUtil.java @@ -0,0 +1,26 @@ +package mate.academy.util.db; + +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/mate"; + private static final Properties DB_PROPERTIES; + + static { + DB_PROPERTIES = new Properties(); + DB_PROPERTIES.put("user", "root"); + DB_PROPERTIES.put("password", "12345678"); + 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, DB_PROPERTIES); + } +} diff --git a/src/main/resources/init_db.sql b/src/main/resources/init_db.sql new file mode 100644 index 00000000..d76795fe --- /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(6, 2) NOT NULL, + is_deleted TINYINT NOT NULL DEFAULT 0); \ No newline at end of file