Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

created UtilConnection; #398

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class Main {
}
```
**WARNING!!!** Path to your project must contain only english letters. Also, it mustn't contain spaces. In other case `Injector` won't work correctly.
- Your table should be named `books` and contain these columns: `id`, `title`, `price`.
- Your table should be named `book` and contain these columns: `id`, `title`, `price`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but i have table dook with columns: id, title and price

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to the naming convention, table in DB should be plural

### Java classes structure:
- Book

Expand Down
20 changes: 10 additions & 10 deletions checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Try to avoid code duplication. Especially, when you are working with ResultSet.
Move retrieving data from ResultSet into Entity object to a separate private method.

* Don't make `books.title` UNIQUE. This is not required in this task.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert file

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

title doesn`t unique

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, revert changes in checklist file. If you have some questions please ask in chat

* Don't make `book.title` UNIQUE. This is not required in this task.

* When creating a table in MySQL, use `bigint` column type for storing id.

Expand All @@ -12,11 +12,11 @@

* Use `PreparedStatement` over `Statement`, even for a static query with no parameters in `findAll()` method. It's the best practice, and it's slightly faster.

* Column naming (`books.` is a table name in these examples):
* Column naming (`book.` is a table name in these examples):

Wrong: `books.bookTitle`, `books.BOOK_TITLE`
Wrong: `book.bookTitle`, `book.BOOK_TITLE`

Good: `books.title`
Good: `book.title`

* Use `Statement.RETURN_GENERATED_KEYS` only in `create` statement, it's not needed in other methods.

Expand Down Expand Up @@ -48,19 +48,19 @@ Good: `books.title`

- Bad practice:
```sql
insert into books (..) VALUES (..);
insert into book (..) VALUES (..);
```
- Good practice:
```sql
INSERT INTO books (..) VALUES (..);
INSERT INTO book (..) VALUES (..);
```
* Let's save each query in a separate variable.
- Bad practice:
```java
public List<Book> findAll() {
try (Connection connection = ConnectionUtil.getConnection()
PreparedStatement preparedStatement = connection
.prepareStatement("SELECT * FROM books")) { // it's bad
.prepareStatement("SELECT * FROM book")) { // it's bad
...
} catch (SQLException ex) {
...
Expand All @@ -70,7 +70,7 @@ Good: `books.title`
- Good practice:
```java
public List<Book> findAll() {
String query = "SELECT * FROM books"; // it's good
String query = "SELECT * FROM book"; // it's good
try (Connection connection = ConnectionUtil.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query)) {
...
Expand Down Expand Up @@ -105,11 +105,11 @@ Good: `books.title`

- Bad practice:
```sql
SELECT * FROM schemaname.books WHERE id = 1;
SELECT * FROM schemaname.book WHERE id = 1;
```
- Good practice:
```sql
SELECT * FROM books WHERE id = 1;
SELECT * FROM book WHERE id = 1;
```
* When you convert `ResultSet` to `Book` better create an object using setters or constructor but not both of them, because it's not consistent to use both ways of initialization of object.

Expand Down
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
</maven.checkstyle.plugin.configLocation>
</properties>

<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
Expand Down
24 changes: 23 additions & 1 deletion src/main/java/mate/academy/Main.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
package mate.academy;

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

public class Main {
public static void main(String[] args) {
private static final Injector injector = Injector.getInstance("mate.academy.dao");

public static void main(String[] args) {
BookDao bookDao = (BookDao) injector.getInstance(BookDao.class);
List<Book> books = List.of(new Book("First Book", BigDecimal.valueOf(45)),
new Book("Second Book", BigDecimal.valueOf(12)),
new Book("Third Book", BigDecimal.valueOf(26)));
for (Book book : books) {
bookDao.create(book);
}
bookDao.findById(1L);
System.out.println(bookDao.findAll());
Book book = new Book();
book.setId(43L);
book.setTitle("Update First Book");
book.setPrice(BigDecimal.valueOf(45));
bookDao.update(book);
bookDao.deleteById(43L);
}
}
17 changes: 17 additions & 0 deletions src/main/java/mate/academy/dao/BookDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package mate.academy.dao;

import java.util.List;
import java.util.Optional;
import mate.academy.entity.Book;

public interface BookDao {
Book create(Book book);

Optional<Book> findById(Long id);

List<Book> findAll();

Book update(Book book);

boolean deleteById(Long id);
}
118 changes: 118 additions & 0 deletions src/main/java/mate/academy/dao/BookDaoImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
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.sql.Types;
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.ConnectionUtil;

@Dao
public class BookDaoImpl implements BookDao {
private static final String CREATE_SQL = "INSERT INTO book (title, price) VALUES (?, ?)";
private static final String FIND_BY_ID_SQL = "SELECT * FROM book WHERE id = ?";
private static final String FIND_ALL_SQL = "SELECT * FROM book";
private static final String UPDATE_BY_ID_SQL = "UPDATE book SET title = ?, "
+ "price = ? WHERE id = ?";
private static final String DELETE_BY_ID_SQL = "DELETE FROM book WHERE id = ?";

@Override
public Book create(Book book) {
try (Connection connection = ConnectionUtil.getConnection();
PreparedStatement statement = connection
.prepareStatement(CREATE_SQL, Statement.RETURN_GENERATED_KEYS)) {
statement.setString(1, book.getTitle());
statement.setBigDecimal(2, book.getPrice());
int rowsAffected = statement.executeUpdate();
if (rowsAffected < 1) {
throw new DataProcessingException("At least one row was expected to be affected, "
+ "but 0 rows were affected");
}
ResultSet generatedKeys = statement.getGeneratedKeys();
if (generatedKeys.next()) {
book.setId(generatedKeys.getLong(1));
}
} catch (SQLException e) {
throw new DataProcessingException("An error occurred while creating the book", e);
}
return book;
}

@Override
public Optional<Book> findById(Long id) {
Book book = new Book();
try (Connection connection = ConnectionUtil.getConnection();
PreparedStatement statement = connection
.prepareStatement(FIND_BY_ID_SQL)) {
statement.setObject(1, id, Types.BIGINT);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
book = mapResultSet(resultSet);
}
} catch (SQLException e) {
throw new DataProcessingException("Could not find book with id: " + id, e);
}
return Optional.of(book);
}

@Override
public List<Book> findAll() {
try (Connection connection = ConnectionUtil.getConnection();
PreparedStatement statement = connection.prepareStatement(FIND_ALL_SQL)) {
List<Book> books = new ArrayList<>();
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
Book book = mapResultSet(resultSet);
books.add(book);
}
return books;
} catch (SQLException e) {
throw new DataProcessingException("Could not find all book", e);
}
}

@Override
public Book update(Book book) {
try (Connection connection = ConnectionUtil.getConnection();
PreparedStatement statement = connection.prepareStatement(UPDATE_BY_ID_SQL)) {
statement.setObject(1, book.getTitle(), Types.VARCHAR);
statement.setObject(2, book.getPrice(), Types.DECIMAL);
statement.setObject(3, book.getId(), Types.BIGINT);

int rowsAffected = statement.executeUpdate();
if (rowsAffected < 1) {
throw new DataProcessingException("At least one row was expected to be affected, "
+ "but 0 rows were affected");
}
} catch (SQLException e) {
throw new DataProcessingException("An error occurred while updating the book", e);
}
return book;
}

@Override
public boolean deleteById(Long id) {
try (Connection connection = ConnectionUtil.getConnection();
PreparedStatement statement = connection.prepareStatement(DELETE_BY_ID_SQL)) {
statement.setObject(1, id, Types.BIGINT);
return statement.executeUpdate() > 0;
} catch (SQLException e) {
throw new DataProcessingException("An error occurred while deleting the book", e);
}
}

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

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 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
+ '}';
}
}
11 changes: 11 additions & 0 deletions src/main/java/mate/academy/exception/DataProcessingException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package mate.academy.exception;

public class DataProcessingException extends RuntimeException {
public DataProcessingException(String cause, Throwable e) {
super(cause, e);
}

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

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/books";
private static final Properties DB_PROPERTIES;

static {
DB_PROPERTIES = new Properties();
DB_PROPERTIES.put("user", "root");
DB_PROPERTIES.put("password", "6855");

try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException("Can`t load JDBC driver", e);
}
}

public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(DB_URL, DB_PROPERTIES);
}
}
5 changes: 5 additions & 0 deletions src/main/resources/init_db.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE TABLE book (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
CREATE TABLE book (
CREATE TABLE books (

id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255),
price DECIMAL
);
Loading