Skip to content

Commit

Permalink
created Book entity and DAO implementation
Browse files Browse the repository at this point in the history
- created Book entity, BookDao interface, and BookDaoImpl class with CRUD operations;
- added database connection management through ConnectionManager and properties handling via PropertiesUtil.
- Updated Main to test CRUD operations.
  • Loading branch information
chertiav committed Jul 26, 2024
1 parent bc1d800 commit 0f0abdc
Show file tree
Hide file tree
Showing 11 changed files with 324 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
.idea/*
*.iml
target/*
target/*
9 changes: 9 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,13 @@
</plugins>
</pluginManagement>
</build>

<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.0.0</version>
</dependency>

</dependencies>
</project>
41 changes: 41 additions & 0 deletions src/main/java/mate/academy/Main.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,48 @@
package mate.academy;

import java.math.BigDecimal;
import mate.academy.dao.BookDao;
import mate.academy.entity.Book;
import mate.academy.lib.Injector;

public class Main {
private static final Injector injector = Injector.getInstance("mate.academy");

public static void main(String[] args) {
Book coreJavaVol1 = new Book();
coreJavaVol1.setTitle("Core Java: Fundamentals, Volume 1");
coreJavaVol1.setPrice(new BigDecimal("50.59"));

Book coreJavaVol2 = new Book();
coreJavaVol2.setTitle("Core Java: Advanced Features, Volume 2");
coreJavaVol2.setPrice(new BigDecimal("48.38"));

Book javaSE8 = new Book();
javaSE8.setTitle("Java SE 8. Programmer I Exam Guide");
javaSE8.setPrice(new BigDecimal("35.99"));

BookDao bookDao = (BookDao) injector.getInstance(BookDao.class);

// create
System.out.println(bookDao.create(coreJavaVol1));
System.out.println(bookDao.create(coreJavaVol2));
System.out.println(bookDao.create(javaSE8));

// findById
System.out.println(bookDao.findById(1L));
System.out.println(bookDao.findById(2L));
System.out.println(bookDao.findById(3L));

// findAll
System.out.println(bookDao.findAll());

// update
coreJavaVol1.setId(1L);
coreJavaVol1.setPrice(new BigDecimal(60));
System.out.println(bookDao.update(coreJavaVol1));

// deleteById
System.out.println(bookDao.delete(1L));

}
}
16 changes: 16 additions & 0 deletions src/main/java/mate/academy/dao/BookDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package mate.academy.dao;

import java.util.List;
import java.util.Optional;

public interface BookDao<K, E> {
E create(E book);

Optional<E> findById(K id);

List<E> findAll();

E update(E book);

boolean delete(K id);
}
116 changes: 116 additions & 0 deletions src/main/java/mate/academy/dao/BookDaoImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package mate.academy.dao;

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.entity.Book;
import mate.academy.exception.DataProcessingException;
import mate.academy.lib.Dao;
import mate.academy.util.ConnectionManager;

@Dao
public class BookDaoImpl implements BookDao<Long, Book> {
private static final String SQL_INSERT = "INSERT INTO books (title, price) VALUES (?, ?)";
private static final String SQL_FIND_BY_ID = "SELECT * FROM books WHERE id = ?";
private static final String SQL_FIND_ALL = "SELECT * FROM books";
private static final String SQL_UPDATE = "UPDATE books SET title = ?, price = ? WHERE id = ?";
private static final String SQL_DELETE = "DELETE FROM books WHERE id = ?";

@Override
public Book create(Book book) {
try (Connection connection = ConnectionManager.open();
PreparedStatement statement = connection.prepareStatement(SQL_INSERT,
Statement.RETURN_GENERATED_KEYS)) {
statement.setString(1, book.getTitle());
statement.setBigDecimal(2, book.getPrice());
int affectedRows = statement.executeUpdate();
validateAffectedRows(affectedRows);
ResultSet generatedKeys = statement.getGeneratedKeys();
if (generatedKeys.next()) {
book.setId(generatedKeys.getLong(1));
}
return book;
} catch (SQLException e) {
throw new DataProcessingException("Can't add new book: " + book, e);
}
}

@Override
public Optional<Book> findById(Long id) {
try (Connection connection = ConnectionManager.open();
PreparedStatement statement = connection.prepareStatement(SQL_FIND_BY_ID)) {
statement.setLong(1, id);
ResultSet resultSet = statement.executeQuery();
Book book = null;
if (resultSet.next()) {
book = buildBook(resultSet);
}
return Optional.ofNullable(book);
} catch (SQLException e) {
throw new DataProcessingException("Can't find book with id: " + id, e);
}
}

@Override
public List<Book> findAll() {
try (Connection connection = ConnectionManager.open();
PreparedStatement statement = connection.prepareStatement(SQL_FIND_ALL)) {
ResultSet resultSet = statement.executeQuery();
List<Book> books = new ArrayList<>();
while (resultSet.next()) {
books.add(buildBook(resultSet));
}
return books;
} catch (SQLException e) {
throw new DataProcessingException("Can't retrieve books", e);
}
}

@Override
public Book update(Book book) {
try (Connection connection = ConnectionManager.open();
PreparedStatement statement = connection.prepareStatement(SQL_UPDATE)) {
statement.setString(1, book.getTitle());
statement.setBigDecimal(2, book.getPrice());
statement.setLong(3, book.getId());
int updateCount = statement.executeUpdate();
validateAffectedRows(updateCount);
return book;
} catch (SQLException e) {
throw new DataProcessingException("Can't update book: " + book, e);
}
}

@Override
public boolean delete(Long id) {
try (Connection connection = ConnectionManager.open();
PreparedStatement statement = connection.prepareStatement(SQL_DELETE)) {
statement.setLong(1, id);
int deleteCount = statement.executeUpdate();
return deleteCount > 0;
} catch (SQLException e) {
throw new DataProcessingException("Can't delete book with id: " + id, e);
}
}

private static void validateAffectedRows(int affectedRows) {
if (affectedRows < 1) {
throw new DataProcessingException(
"Expected to insert at least one row, but inserted 0 rows",
null);
}
}

private static Book buildBook(ResultSet resultSet) throws SQLException {
return new Book(
resultSet.getLong("id"),
resultSet.getString("title"),
resultSet.getBigDecimal("price")
);
}
}
51 changes: 51 additions & 0 deletions src/main/java/mate/academy/entity/Book.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package mate.academy.entity;

import java.math.BigDecimal;

public class Book {
private Long id;
private String title;
private BigDecimal price;

public Book(Long id, String title, BigDecimal price) {
this.id = id;
this.title = title;
this.price = price;
}

public Book() {
}

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
+ '}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package mate.academy.exception;

public class DataProcessingException extends RuntimeException {
public DataProcessingException(String message, Throwable cause) {
super(message, cause);
}
}
40 changes: 40 additions & 0 deletions src/main/java/mate/academy/util/ConnectionManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package mate.academy.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import mate.academy.exception.DataProcessingException;

public class ConnectionManager {
private static final String USERNAME_KEY = "db.username";
private static final String PASSWORD_KEY = "db.password";
private static final String URL_KEY = "db.url";

static {
loadDriver();
}

public ConnectionManager() {
}

public static Connection open() {
try {
return DriverManager.getConnection(
PropertiesUtil.get(URL_KEY),
PropertiesUtil.get(USERNAME_KEY),
PropertiesUtil.get(PASSWORD_KEY)
);
} catch (SQLException e) {
throw new DataProcessingException("Failed to establish database connection", e);
}
}

private static void loadDriver() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new DataProcessingException("Can't load JDBC driver: ", e);
}
}

}
31 changes: 31 additions & 0 deletions src/main/java/mate/academy/util/PropertiesUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package mate.academy.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import mate.academy.exception.DataProcessingException;

public class PropertiesUtil {
private static final String PROPERTIES_FILE = "application.properties";
private static final Properties PROPERTIES = new Properties();

static {
loadProperties();
}

public PropertiesUtil() {
}

public static String get(String key) {
return PROPERTIES.getProperty(key);
}

private static void loadProperties() {
try (InputStream inputStream = PropertiesUtil.class.getClassLoader()
.getResourceAsStream(PROPERTIES_FILE)) {
PROPERTIES.load(inputStream);
} catch (IOException e) {
throw new DataProcessingException("Can't get data from: " + PROPERTIES_FILE, e);
}
}
}
3 changes: 3 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
db.url=jdbc:mysql://localhost:3306/book_repository
db.username=root
db.password=1111
9 changes: 9 additions & 0 deletions src/main/resources/init_db.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE DATABASE book_repository;

USE book_repository;

CREATE TABLE books (
id SERIAL PRIMARY KEY,
title VARCHAR(128),
price DECIMAL(10, 2)
);

0 comments on commit 0f0abdc

Please sign in to comment.