diff --git a/pom.xml b/pom.xml
index 683e84ec..067e5f75 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,13 @@
https://raw.githubusercontent.com/mate-academy/style-guides/master/java/checkstyle.xml
-
+
+
+ com.mysql
+ mysql-connector-j
+ 8.3.0
+
+
diff --git a/src/main/java/mate/academy/Main.java b/src/main/java/mate/academy/Main.java
index 0058fbf9..c53a7e16 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.setTitle("Dune");
+ book.setPrice(BigDecimal.valueOf(19.99));
+ bookDao.create(book);
+
+ // Testing other methods
+ Optional foundBook = bookDao.findById(book.getId());
+ foundBook.ifPresent(System.out::println);
+
+ List allBooks = bookDao.findAll();
+ System.out.println("All Books: " + allBooks);
+
+ book.setTitle("Lisan al gaib");
+ bookDao.update(book);
+ System.out.println("Updated Book: " + book);
+ boolean deleted = bookDao.deleteById(book.getId());
+ System.out.println("Deleted: " + deleted);
}
}
diff --git a/src/main/java/mate/academy/connection/ConnectionUtil.java b/src/main/java/mate/academy/connection/ConnectionUtil.java
new file mode 100644
index 00000000..11f906a3
--- /dev/null
+++ b/src/main/java/mate/academy/connection/ConnectionUtil.java
@@ -0,0 +1,35 @@
+package mate.academy.connection;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Properties;
+import mate.academy.exception.DataProcessingException;
+
+public class ConnectionUtil {
+ private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
+ private static final String DB_PATH = "jdbc:mysql://localhost:3306/jdbc";
+ private static final String USER = "root";
+ private static final String PASSWORD = "MySQL1234";
+ private static final Properties PROPERTIES;
+
+ static {
+ PROPERTIES = new Properties();
+ PROPERTIES.put("user", USER);
+ PROPERTIES.put("password", PASSWORD);
+
+ try {
+ Class.forName(DRIVER);
+ } catch (ClassNotFoundException e) {
+ throw new DataProcessingException("Something wrong with Driver", e);
+ }
+ }
+
+ public static Connection getConnection() {
+ try {
+ return DriverManager.getConnection(DB_PATH, PROPERTIES);
+ } catch (SQLException e) {
+ throw new DataProcessingException("Failed to establish database connection", e);
+ }
+ }
+}
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..9fc4cce4
--- /dev/null
+++ b/src/main/java/mate/academy/dao/BookDao.java
@@ -0,0 +1,18 @@
+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..705f3baf
--- /dev/null
+++ b/src/main/java/mate/academy/dao/BookDaoImpl.java
@@ -0,0 +1,138 @@
+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.connection.ConnectionUtil;
+import mate.academy.exception.DataProcessingException;
+import mate.academy.lib.Dao;
+import mate.academy.model.Book;
+
+@Dao
+public class BookDaoImpl implements BookDao {
+ private static final int COLUMN_TITLE = 1;
+ private static final int COLUMN_PRICE = 2;
+ private static final int COLUMN_ID = 3;
+ private static final String ID = "id";
+ private static final String TITLE = "title";
+ private static final String PRICE = "price";
+
+ @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(COLUMN_TITLE, book.getTitle());
+ statement.setBigDecimal(COLUMN_PRICE, book.getPrice());
+
+ int affectedRows = statement.executeUpdate();
+ isUpdated(affectedRows, book);
+ ResultSet generatedKeys = statement.getGeneratedKeys();
+ if (generatedKeys.next()) {
+ Long id = generatedKeys.getObject(COLUMN_TITLE, Long.class);
+ book.setId(id);
+ }
+ } catch (SQLException e) {
+ throw new DataProcessingException("Can't save new book: " + book, e);
+ }
+ return book;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ Book book = new Book();
+ String sql = "SELECT * FROM books WHERE id = ?";
+ try (Connection connection = ConnectionUtil.getConnection();
+ PreparedStatement statement = connection.prepareStatement(sql)) {
+ statement.setLong(COLUMN_TITLE, id);
+ ResultSet resultSet = statement.executeQuery();
+ if (resultSet.next()) {
+ mapToBook(resultSet);
+ }
+ } catch (SQLException e) {
+ throw new DataProcessingException("Can't get a book by id " + id, e);
+ }
+ return Optional.of(book);
+ }
+
+ @Override
+ public List findAll() {
+ List books = new ArrayList<>();
+ String sql = "SELECT * FROM books";
+ try (Connection connection = ConnectionUtil.getConnection();
+ PreparedStatement statement = connection.prepareStatement(sql)) {
+ ResultSet resultSet = statement.executeQuery();
+ while (resultSet.next()) {
+ Book book = new Book();
+ book = mapToBook(resultSet);
+ books.add(book);
+ }
+ } catch (SQLException e) {
+ throw new DataProcessingException("Can't fetch books", 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.setString(COLUMN_TITLE, book.getTitle());
+ statement.setBigDecimal(COLUMN_PRICE, book.getPrice());
+ statement.setLong(COLUMN_ID, book.getId());
+
+ int affectedRows = statement.executeUpdate();
+ isUpdated(affectedRows, book);
+ } catch (SQLException e) {
+ throw new DataProcessingException("Can't update a book: " + book, e);
+ }
+ return book;
+ }
+
+ @Override
+ public boolean deleteById(Long id) {
+ String sql = "DELETE FROM books WHERE id = ?";
+ int affectedRows;
+ try (Connection connection = ConnectionUtil.getConnection();
+ PreparedStatement statement = connection.prepareStatement(sql)) {
+ statement.setLong(COLUMN_TITLE, id);
+ affectedRows = statement.executeUpdate();
+ } catch (SQLException e) {
+ throw new DataProcessingException("Can't delete a book with id: " + id, e);
+ }
+ return affectedRows > 0;
+ }
+
+ private boolean isUpdated(int affectedRows, Book book) {
+ if (affectedRows < 1) {
+ throw new DataProcessingException(
+ "Expected to update at least one row, but updated nothing: "
+ + book);
+ }
+ return true;
+ }
+
+ private Book mapToBook(ResultSet resultSet) {
+ Book book = new Book();
+ try {
+ long columnId = resultSet.getObject(ID, Long.class);
+ Object columnPrice = resultSet.getObject(PRICE);
+ String columnTitle = resultSet.getString(TITLE);
+ book.setPrice((BigDecimal) columnPrice);
+ book.setTitle(columnTitle);
+ book.setId(columnId);
+ } catch (SQLException e) {
+ throw new DataProcessingException("Can`t get result from DB");
+ }
+ return book;
+ }
+}
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..02f156f9
--- /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, Throwable ex) {
+ super(message, ex);
+ }
+
+ public DataProcessingException(String message) {
+ super(message);
+ }
+}
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..1cab86c3
--- /dev/null
+++ b/src/main/java/mate/academy/model/Book.java
@@ -0,0 +1,41 @@
+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/resources/init_db.sql b/src/main/resources/init_db.sql
new file mode 100644
index 00000000..1b53caa3
--- /dev/null
+++ b/src/main/resources/init_db.sql
@@ -0,0 +1,6 @@
+USE jdbc;
+CREATE TABLE books (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ title VARCHAR(255),
+ price DECIMAL(10,2)
+);