From 818e0c35878f730ba43820370f1ae2301b8d5f12 Mon Sep 17 00:00:00 2001 From: tboychuk Date: Thu, 23 Aug 2018 14:49:21 +0300 Subject: [PATCH 1/7] Complete exercise ProductDaoImpl.java --- .../java/com/bobocode/dao/ProductDaoImpl.java | 190 +++++++++++++++++- 1 file changed, 185 insertions(+), 5 deletions(-) diff --git a/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java b/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java index a6e0d8c..cd95341 100644 --- a/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java +++ b/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java @@ -1,11 +1,21 @@ package com.bobocode.dao; +import com.bobocode.exception.DaoOperationException; import com.bobocode.model.Product; import javax.sql.DataSource; +import java.sql.*; +import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class ProductDaoImpl implements ProductDao { + private static String INSERT_SQL = "INSERT INTO products(name, producer, price, expiration_date) VALUES (?, ?, ?, ?);"; + private static String SELECT_ALL_SQL = "SELECT * FROM products;"; + private static String SELECT_BY_ID_SQL = "SELECT * FROM products WHERE id = ?;"; + private static String UPDATE_BY_ID_SLQ = "UPDATE products SET name = ?, producer = ?, price = ?, expiration_date = ? WHERE id = ?;"; + private static String REMOVE__BY_ID_SQL = "DELETE FROM products WHERE id = ?;"; + private DataSource dataSource; public ProductDaoImpl(DataSource dataSource) { @@ -14,27 +24,197 @@ public ProductDaoImpl(DataSource dataSource) { @Override public void save(Product product) { - throw new UnsupportedOperationException("None of these methods will work unless you implement them!");// todo + Objects.requireNonNull(product); + try (Connection connection = dataSource.getConnection()) { // try-with-resources will automatically close connection + saveProduct(product, connection); + } catch (SQLException e) { + throw new DaoOperationException(String.format("Error saving product: %s", product), e); + } + } + + private void saveProduct(Product product, Connection connection) throws SQLException { + PreparedStatement insertStatement = prepareInsertStatement(product, connection); + executeUpdate(insertStatement); + Long id = fetchGeneratedId(insertStatement); + product.setId(id); + } + + private PreparedStatement prepareInsertStatement(Product product, Connection connection) { + try { + PreparedStatement insertStatement = connection.prepareStatement(INSERT_SQL, + PreparedStatement.RETURN_GENERATED_KEYS); // this parameter will configure query to ask db for a generated keys + return fillInsertStatementWithParameters(insertStatement, product); + } catch (SQLException e) { + throw new DaoOperationException(String.format("Cannot prepare statement for product: %s", product), e); + } + } + + private PreparedStatement fillInsertStatementWithParameters(PreparedStatement insertStatement, Product product) throws SQLException { + insertStatement.setString(1, product.getName()); + insertStatement.setString(2, product.getProducer()); + insertStatement.setBigDecimal(3, product.getPrice()); + insertStatement.setDate(4, Date.valueOf(product.getExpirationDate())); + return insertStatement; + } + + private void executeUpdate(PreparedStatement insertStatement) throws SQLException { + int rowsAffected = insertStatement.executeUpdate(); // returns number of rows that were changed + if (rowsAffected == 0) { + throw new DaoOperationException("Nothing has been changed"); + } + } + + private Long fetchGeneratedId(PreparedStatement insertStatement) throws SQLException { + // this method allows to retrieve IDs that were generated by the database during insert statement + ResultSet generatedKeys = insertStatement.getGeneratedKeys(); + if (generatedKeys.next()) { // you need to call next() because cursor is located before the first row + return generatedKeys.getLong(1); + } else { // if next() returned false it means that database didn't return any IDs + throw new DaoOperationException("Can not obtain product ID"); + } } @Override public List findAll() { - throw new UnsupportedOperationException("None of these methods will work unless you implement them!");// todo + try (Connection connection = dataSource.getConnection()) { + return findAllProducts(connection); + } catch (SQLException e) { + throw new DaoOperationException("Error finding all products", e); + } + } + + private List findAllProducts(Connection connection) throws SQLException { + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(SELECT_ALL_SQL); + return collectToList(resultSet); + } + + private List collectToList(ResultSet resultSet) throws SQLException { + List products = new ArrayList<>(); + while (resultSet.next()) { + Product product = parseRow(resultSet); + products.add(product); + } + return products; + } + + private Product parseRow(ResultSet resultSet) { + try { + return createFromResultSet(resultSet); + } catch (SQLException e) { + throw new DaoOperationException("Cannot parse row to create product instance", e); + } + } + + private Product createFromResultSet(ResultSet resultSet) throws SQLException { + Product product = new Product(); + product.setId(resultSet.getLong("id")); + product.setName(resultSet.getString("name")); + product.setProducer(resultSet.getString("producer")); + product.setPrice(resultSet.getBigDecimal("price")); + product.setExpirationDate(resultSet.getDate("expiration_date").toLocalDate()); + product.setCreationTime(resultSet.getTimestamp("creation_time").toLocalDateTime()); + return product; } @Override public Product findOne(Long id) { - throw new UnsupportedOperationException("None of these methods will work unless you implement them!");// todo + Objects.requireNonNull(id); + try (Connection connection = dataSource.getConnection()) { + return findProductById(id, connection); + } catch (SQLException e) { + throw new DaoOperationException(String.format("Error finding product by id = %d", id), e); + } + } + + private Product findProductById(Long id, Connection connection) throws SQLException { + PreparedStatement selectByIdStatement = prepareSelectByIdStatement(id, connection); + ResultSet resultSet = selectByIdStatement.executeQuery(); + return retrieveResult(resultSet, id); + } + + + private PreparedStatement prepareSelectByIdStatement(Long id, Connection connection) { + try { + PreparedStatement selectByIdStatement = connection.prepareStatement(SELECT_BY_ID_SQL); + selectByIdStatement.setLong(1, id); + return selectByIdStatement; + } catch (SQLException e) { + throw new DaoOperationException(String.format("Cannot prepare select by id statement for id = %d", id), e); + } + } + + private Product retrieveResult(ResultSet resultSet, Long id) throws SQLException { + // before parsing ResultSet we need to call next() since cursor is located before the first line + boolean resultIsNotEmpty = resultSet.next(); + if (resultIsNotEmpty) { + return parseRow(resultSet); + } else { // if next() returned false it means that database returned an empty response + throw new DaoOperationException(String.format("Product with id = %d does not exist", id)); + } } @Override public void update(Product product) { - throw new UnsupportedOperationException("None of these methods will work unless you implement them!");// todo + Objects.requireNonNull(product); + try (Connection connection = dataSource.getConnection()) { + updateProduct(product, connection); + } catch (SQLException e) { + throw new DaoOperationException(String.format("Error updating product: %s", product), e); + } + } + + private void updateProduct(Product product, Connection connection) throws SQLException { + checkIfExists(product, connection); + PreparedStatement updateStatement = prepareUpdateStatement(product, connection); + executeUpdate(updateStatement); + } + + private PreparedStatement prepareUpdateStatement(Product product, Connection connection) { + try { + PreparedStatement updateStatement = connection.prepareStatement(UPDATE_BY_ID_SLQ); + updateStatement.setString(1, product.getName()); + updateStatement.setString(2, product.getProducer()); + updateStatement.setBigDecimal(3, product.getPrice()); + updateStatement.setDate(4, Date.valueOf(product.getExpirationDate())); + updateStatement.setLong(5, product.getId()); + return updateStatement; + } catch (SQLException e) { + throw new DaoOperationException(String.format("Cannot prepare update statement for product: %s", product), e); + } } @Override public void remove(Product product) { - throw new UnsupportedOperationException("None of these methods will work unless you implement them!");// todo + Objects.requireNonNull(product); + try (Connection connection = dataSource.getConnection()) { + removeProduct(product, connection); + } catch (SQLException e) { + throw new DaoOperationException(String.format("Error removing product by id = %d", product.getId()), e); + } + } + + private void removeProduct(Product product, Connection connection) throws SQLException { + checkIfExists(product, connection); + PreparedStatement removeStatement = prepareRemoveStatement(product, connection); + executeUpdate(removeStatement); } + private PreparedStatement prepareRemoveStatement(Product product, Connection connection) { + try { + PreparedStatement removeStatement = connection.prepareStatement(REMOVE__BY_ID_SQL); + removeStatement.setLong(1, product.getId()); + return removeStatement; + } catch (SQLException e) { + throw new DaoOperationException(String.format("Cannot prepare statement for product: %s", product), e); + } + } + + private void checkIfExists(Product product, Connection connection) throws SQLException { + if (product.getId() == null) { + throw new DaoOperationException("Cannot find a product without ID"); + } + findProductById(product.getId(), connection); // this method will throw an exception if product doesn't exist + } } + From 2fa1d7267bf15003fc3740fe85b936cb03a45601 Mon Sep 17 00:00:00 2001 From: tboychuk Date: Mon, 27 Aug 2018 16:33:25 +0300 Subject: [PATCH 2/7] Complete exercise AccountDbInitializer.java --- .../com/bobocode/AccountDbInitializer.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/account-db-initializer/src/main/java/com/bobocode/AccountDbInitializer.java b/account-db-initializer/src/main/java/com/bobocode/AccountDbInitializer.java index 9f185f9..2a8ae2f 100644 --- a/account-db-initializer/src/main/java/com/bobocode/AccountDbInitializer.java +++ b/account-db-initializer/src/main/java/com/bobocode/AccountDbInitializer.java @@ -1,7 +1,9 @@ package com.bobocode; import javax.sql.DataSource; +import java.sql.Connection; import java.sql.SQLException; +import java.sql.Statement; /** * {@link AccountDbInitializer} provides an API that allow to initialize (create) an Account table in the database @@ -28,6 +30,20 @@ public AccountDbInitializer(DataSource dataSource) { * @throws SQLException */ public void init() throws SQLException { - throw new UnsupportedOperationException("It's your job to make it work!"); // todo + try (Connection connection = dataSource.getConnection()) { + Statement statement = connection.createStatement(); + statement.execute("CREATE TABLE account(" + + "id BIGINT," + + " email VARCHAR(255) NOT NULL," + + " first_name VARCHAR(255) NOT NULL," + + " last_name VARCHAR(255) NOT NULL," + + " gender VARCHAR(255) NOT NULL," + + " birthday DATE NOT NULL," + + " balance DECIMAL(19,4)," + + " creation_time TIMESTAMP NOT NULL DEFAULT now()," + + " CONSTRAINT account_pk PRIMARY KEY (id)," + + " CONSTRAINT account_email_uq UNIQUE (email)" + + ");"); + } } } From 406175657dfbe51e93ebcd29b5869ac795396217 Mon Sep 17 00:00:00 2001 From: tboychuk Date: Tue, 28 Aug 2018 15:28:14 +0300 Subject: [PATCH 3/7] Complete exercise WallStreetDbInitializer --- .../db/migration/table_initialization.sql | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/wall-street-db-initializer/src/main/resources/db/migration/table_initialization.sql b/wall-street-db-initializer/src/main/resources/db/migration/table_initialization.sql index 1554122..240615f 100644 --- a/wall-street-db-initializer/src/main/resources/db/migration/table_initialization.sql +++ b/wall-street-db-initializer/src/main/resources/db/migration/table_initialization.sql @@ -25,4 +25,31 @@ A sales group can consists of more than one broker, while each broker can be ass */ --- TODO: write SQL script to create a database tables according to the requirements +CREATE TABLE IF NOT EXISTS broker ( + id BIGINT, + username VARCHAR(255) NOT NULL, + first_name VARCHAR(255) NOT NULL, + last_name VARCHAR(255) NOT NULL, + CONSTRAINT PK_broker PRIMARY KEY (id), + CONSTRAINT UQ_broker_username UNIQUE (username) +); + + +CREATE TABLE IF NOT EXISTS sales_group ( + id BIGINT, + name VARCHAR(255) NOT NULL, + transaction_type VARCHAR(255) NOT NULL, + max_transaction_amount INT NOT NULL, + CONSTRAINT PK_sales_group PRIMARY KEY (id), + CONSTRAINT UQ_sales_group_name UNIQUE (name) +); + + +CREATE TABLE IF NOT EXISTS broker_sales_group ( + broker_id BIGINT NOT NULL, + sales_group_id BIGINT NOT NULL, + CONSTRAINT FK_broker_sales_group_broker FOREIGN KEY (broker_id) REFERENCES broker, + CONSTRAINT FK_broker_sales_group_sales_group FOREIGN KEY (sales_group_id) REFERENCES sales_group, + CONSTRAINT UQ_broker_sales_group_broker_id_sales_group_id UNIQUE (broker_id, sales_group_id) +); + From 824e1802913c4aac8f9fdd07ed67ec721c21966b Mon Sep 17 00:00:00 2001 From: tboychuk Date: Wed, 29 Aug 2018 13:22:42 +0300 Subject: [PATCH 4/7] Complete exercise UserProfilesDbInitializer --- .../db/migration/table_initialization.sql | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/user-profile-db-initializer/src/main/resources/db/migration/table_initialization.sql b/user-profile-db-initializer/src/main/resources/db/migration/table_initialization.sql index 6754871..011a827 100644 --- a/user-profile-db-initializer/src/main/resources/db/migration/table_initialization.sql +++ b/user-profile-db-initializer/src/main/resources/db/migration/table_initialization.sql @@ -22,4 +22,23 @@ should have a column that stores primary key from a parent table, which is a for */ --- TODO: implement the SQL according to the description \ No newline at end of file +CREATE TABLE IF NOT EXISTS users ( + id BIGINT, + first_name VARCHAR(255) NOT NULL, + last_name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + birthday DATE NOT NULL, + CONSTRAINT users_PK PRIMARY KEY (id), + CONSTRAINT users_email_AK UNIQUE (email) +); + +CREATE TABLE IF NOT EXISTS profiles ( + user_id BIGINT, + city VARCHAR(255), + job_position VARCHAR(255), + company VARCHAR(255), + education VARCHAR(255), + CONSTRAINT profiles_PK PRIMARY KEY (user_id), + CONSTRAINT profiles_users_FK FOREIGN KEY (user_id) REFERENCES users +); + From be0ae279d11676898e2d80caa3560d4f406b748b Mon Sep 17 00:00:00 2001 From: tboychuk Date: Thu, 30 Aug 2018 09:22:59 +0300 Subject: [PATCH 5/7] Update complete implementation --- .../src/main/resources/db/migration/table_initialization.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wall-street-db-initializer/src/main/resources/db/migration/table_initialization.sql b/wall-street-db-initializer/src/main/resources/db/migration/table_initialization.sql index 17d6ca2..1e0e2d7 100644 --- a/wall-street-db-initializer/src/main/resources/db/migration/table_initialization.sql +++ b/wall-street-db-initializer/src/main/resources/db/migration/table_initialization.sql @@ -47,8 +47,8 @@ CREATE TABLE IF NOT EXISTS sales_group ( CREATE TABLE IF NOT EXISTS broker_sales_group ( broker_id BIGINT NOT NULL, sales_group_id BIGINT NOT NULL, + CONSTRAINT PK_broker_sales_group PRIMARY KEY (broker_id, sales_group_id), CONSTRAINT FK_broker_sales_group_broker FOREIGN KEY (broker_id) REFERENCES broker, - CONSTRAINT FK_broker_sales_group_sales_group FOREIGN KEY (sales_group_id) REFERENCES sales_group, - CONSTRAINT UQ_broker_sales_group_broker_id_sales_group_id UNIQUE (broker_id, sales_group_id) + CONSTRAINT FK_broker_sales_group_sales_group FOREIGN KEY (sales_group_id) REFERENCES sales_group ); From 839f0e506dfa17ba80de4a0c8de40c2faf0d0fb7 Mon Sep 17 00:00:00 2001 From: tboychuk Date: Sun, 11 Nov 2018 22:34:35 +0200 Subject: [PATCH 6/7] Upgrade ProductDaoImpl.java --- .../java/com/bobocode/dao/ProductDaoImpl.java | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java b/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java index cd95341..feb5559 100644 --- a/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java +++ b/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java @@ -10,11 +10,11 @@ import java.util.Objects; public class ProductDaoImpl implements ProductDao { - private static String INSERT_SQL = "INSERT INTO products(name, producer, price, expiration_date) VALUES (?, ?, ?, ?);"; - private static String SELECT_ALL_SQL = "SELECT * FROM products;"; - private static String SELECT_BY_ID_SQL = "SELECT * FROM products WHERE id = ?;"; - private static String UPDATE_BY_ID_SLQ = "UPDATE products SET name = ?, producer = ?, price = ?, expiration_date = ? WHERE id = ?;"; - private static String REMOVE__BY_ID_SQL = "DELETE FROM products WHERE id = ?;"; + private static final String INSERT_SQL = "INSERT INTO products(name, producer, price, expiration_date) VALUES (?, ?, ?, ?);"; + private static final String SELECT_ALL_SQL = "SELECT * FROM products;"; + private static final String SELECT_BY_ID_SQL = "SELECT * FROM products WHERE id = ?;"; + private static final String UPDATE_BY_ID_SLQ = "UPDATE products SET name = ?, producer = ?, price = ?, expiration_date = ? WHERE id = ?;"; + private static final String REMOVE_BY_ID_SQL = "DELETE FROM products WHERE id = ?;"; private DataSource dataSource; @@ -130,10 +130,13 @@ public Product findOne(Long id) { private Product findProductById(Long id, Connection connection) throws SQLException { PreparedStatement selectByIdStatement = prepareSelectByIdStatement(id, connection); ResultSet resultSet = selectByIdStatement.executeQuery(); - return retrieveResult(resultSet, id); + if (resultSet.next()) {// we need to call next() since cursor is located before the first line + return parseRow(resultSet); + } else { // if next() returned false it means that database returned an empty response + throw new DaoOperationException(String.format("Product with id = %d does not exist", id)); + } } - private PreparedStatement prepareSelectByIdStatement(Long id, Connection connection) { try { PreparedStatement selectByIdStatement = connection.prepareStatement(SELECT_BY_ID_SQL); @@ -144,16 +147,6 @@ private PreparedStatement prepareSelectByIdStatement(Long id, Connection connect } } - private Product retrieveResult(ResultSet resultSet, Long id) throws SQLException { - // before parsing ResultSet we need to call next() since cursor is located before the first line - boolean resultIsNotEmpty = resultSet.next(); - if (resultIsNotEmpty) { - return parseRow(resultSet); - } else { // if next() returned false it means that database returned an empty response - throw new DaoOperationException(String.format("Product with id = %d does not exist", id)); - } - } - @Override public void update(Product product) { Objects.requireNonNull(product); @@ -165,7 +158,7 @@ public void update(Product product) { } private void updateProduct(Product product, Connection connection) throws SQLException { - checkIfExists(product, connection); + verifyProductId(product, connection); PreparedStatement updateStatement = prepareUpdateStatement(product, connection); executeUpdate(updateStatement); } @@ -195,14 +188,14 @@ public void remove(Product product) { } private void removeProduct(Product product, Connection connection) throws SQLException { - checkIfExists(product, connection); + verifyProductId(product, connection); PreparedStatement removeStatement = prepareRemoveStatement(product, connection); executeUpdate(removeStatement); } private PreparedStatement prepareRemoveStatement(Product product, Connection connection) { try { - PreparedStatement removeStatement = connection.prepareStatement(REMOVE__BY_ID_SQL); + PreparedStatement removeStatement = connection.prepareStatement(REMOVE_BY_ID_SQL); removeStatement.setLong(1, product.getId()); return removeStatement; } catch (SQLException e) { @@ -210,7 +203,8 @@ private PreparedStatement prepareRemoveStatement(Product product, Connection con } } - private void checkIfExists(Product product, Connection connection) throws SQLException { + // todo: optimize + private void verifyProductId(Product product, Connection connection) throws SQLException { if (product.getId() == null) { throw new DaoOperationException("Cannot find a product without ID"); } From 97b459bd5f92a58b6954e3038f430145bd3687ab Mon Sep 17 00:00:00 2001 From: tboychuk Date: Sun, 31 Mar 2019 15:30:04 +0300 Subject: [PATCH 7/7] Upgrade the solution for ProductDaoImpl.java --- .../java/com/bobocode/dao/ProductDaoImpl.java | 51 +++++++++---------- .../java/com/bobocode/ProductDaoTest.java | 4 +- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java b/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java index feb5559..bc62427 100644 --- a/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java +++ b/product-dao/src/main/java/com/bobocode/dao/ProductDaoImpl.java @@ -34,7 +34,7 @@ public void save(Product product) { private void saveProduct(Product product, Connection connection) throws SQLException { PreparedStatement insertStatement = prepareInsertStatement(product, connection); - executeUpdate(insertStatement); + insertStatement.executeUpdate(); Long id = fetchGeneratedId(insertStatement); product.setId(id); } @@ -43,25 +43,18 @@ private PreparedStatement prepareInsertStatement(Product product, Connection con try { PreparedStatement insertStatement = connection.prepareStatement(INSERT_SQL, PreparedStatement.RETURN_GENERATED_KEYS); // this parameter will configure query to ask db for a generated keys - return fillInsertStatementWithParameters(insertStatement, product); + fillProductStatement(product, insertStatement); + return insertStatement; } catch (SQLException e) { throw new DaoOperationException(String.format("Cannot prepare statement for product: %s", product), e); } } - private PreparedStatement fillInsertStatementWithParameters(PreparedStatement insertStatement, Product product) throws SQLException { - insertStatement.setString(1, product.getName()); - insertStatement.setString(2, product.getProducer()); - insertStatement.setBigDecimal(3, product.getPrice()); - insertStatement.setDate(4, Date.valueOf(product.getExpirationDate())); - return insertStatement; - } - - private void executeUpdate(PreparedStatement insertStatement) throws SQLException { - int rowsAffected = insertStatement.executeUpdate(); // returns number of rows that were changed - if (rowsAffected == 0) { - throw new DaoOperationException("Nothing has been changed"); - } + private void fillProductStatement(Product product, PreparedStatement updateStatement) throws SQLException { + updateStatement.setString(1, product.getName()); + updateStatement.setString(2, product.getProducer()); + updateStatement.setBigDecimal(3, product.getPrice()); + updateStatement.setDate(4, Date.valueOf(product.getExpirationDate())); } private Long fetchGeneratedId(PreparedStatement insertStatement) throws SQLException { @@ -158,21 +151,25 @@ public void update(Product product) { } private void updateProduct(Product product, Connection connection) throws SQLException { - verifyProductId(product, connection); + checkIdIsNotNull(product); PreparedStatement updateStatement = prepareUpdateStatement(product, connection); - executeUpdate(updateStatement); + executeUpdateById(updateStatement, product.getId()); + } + + private void executeUpdateById(PreparedStatement insertStatement, Long productId) throws SQLException { + int rowsAffected = insertStatement.executeUpdate(); // returns number of rows that were changed + if (rowsAffected == 0) { + throw new DaoOperationException(String.format("Product with id = %d does not exist", productId)); + } } private PreparedStatement prepareUpdateStatement(Product product, Connection connection) { try { PreparedStatement updateStatement = connection.prepareStatement(UPDATE_BY_ID_SLQ); - updateStatement.setString(1, product.getName()); - updateStatement.setString(2, product.getProducer()); - updateStatement.setBigDecimal(3, product.getPrice()); - updateStatement.setDate(4, Date.valueOf(product.getExpirationDate())); + fillProductStatement(product, updateStatement); updateStatement.setLong(5, product.getId()); return updateStatement; - } catch (SQLException e) { + } catch (Exception e) { throw new DaoOperationException(String.format("Cannot prepare update statement for product: %s", product), e); } } @@ -188,9 +185,9 @@ public void remove(Product product) { } private void removeProduct(Product product, Connection connection) throws SQLException { - verifyProductId(product, connection); + checkIdIsNotNull(product); PreparedStatement removeStatement = prepareRemoveStatement(product, connection); - executeUpdate(removeStatement); + executeUpdateById(removeStatement, product.getId()); } private PreparedStatement prepareRemoveStatement(Product product, Connection connection) { @@ -203,12 +200,10 @@ private PreparedStatement prepareRemoveStatement(Product product, Connection con } } - // todo: optimize - private void verifyProductId(Product product, Connection connection) throws SQLException { + private void checkIdIsNotNull(Product product) { if (product.getId() == null) { - throw new DaoOperationException("Cannot find a product without ID"); + throw new DaoOperationException("Product id cannot be null"); } - findProductById(product.getId(), connection); // this method will throw an exception if product doesn't exist } } diff --git a/product-dao/src/test/java/com/bobocode/ProductDaoTest.java b/product-dao/src/test/java/com/bobocode/ProductDaoTest.java index 86e3787..5007702 100644 --- a/product-dao/src/test/java/com/bobocode/ProductDaoTest.java +++ b/product-dao/src/test/java/com/bobocode/ProductDaoTest.java @@ -214,7 +214,7 @@ public void testUpdateNotStored() { fail("Exception was't thrown"); } catch (Exception e) { assertEquals(DaoOperationException.class, e.getClass()); - assertEquals("Cannot find a product without ID", e.getMessage()); + assertEquals("Product id cannot be null", e.getMessage()); } } @@ -255,7 +255,7 @@ public void testRemoveNotStored() { fail("Exception was't thrown"); } catch (Exception e) { assertEquals(DaoOperationException.class, e.getClass()); - assertEquals("Cannot find a product without ID", e.getMessage()); + assertEquals("Product id cannot be null", e.getMessage()); } }