Work on #404, updated class diagram and javadoc. Passed checkstyle checks
This commit is contained in:
parent
fa077c8be9
commit
3f7ead5ca5
BIN
dao/etc/dao.png
BIN
dao/etc/dao.png
Binary file not shown.
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 39 KiB |
@ -1,45 +1,71 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<class-diagram version="1.1.8" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
|
<class-diagram version="1.1.8" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
|
||||||
associations="true" dependencies="false" nesting-relationships="true">
|
associations="true" dependencies="false" nesting-relationships="true">
|
||||||
<class id="1" language="java" name="com.iluwatar.Customer" project="dao"
|
<class id="1" language="java" name="com.iluwatar.dao.App" project="dao"
|
||||||
file="/dao/src/main/java/com/iluwatar/Customer.java" binary="false" corner="BOTTOM_RIGHT">
|
file="/dao/src/main/java/com/iluwatar/dao/App.java" binary="false" corner="BOTTOM_RIGHT">
|
||||||
<position height="-1" width="-1" x="176" y="337"/>
|
<position height="-1" width="-1" x="910" y="191"/>
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
sort-features="false" accessors="true" visibility="true">
|
sort-features="false" accessors="true" visibility="true">
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
<attributes public="true" package="true" protected="true" private="false" static="true"/>
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
<operations public="true" package="true" protected="true" private="false" static="true"/>
|
||||||
</display>
|
</display>
|
||||||
</class>
|
</class>
|
||||||
<class id="2" language="java" name="com.iluwatar.CustomerDaoImpl" project="dao"
|
<interface id="2" language="java" name="com.iluwatar.dao.CustomerDao" project="dao"
|
||||||
file="/dao/src/main/java/com/iluwatar/CustomerDaoImpl.java" binary="false" corner="BOTTOM_RIGHT">
|
file="/dao/src/main/java/com/iluwatar/dao/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
|
||||||
<position height="-1" width="-1" x="540" y="334"/>
|
<position height="-1" width="-1" x="536" y="187"/>
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
|
||||||
sort-features="false" accessors="true" visibility="true">
|
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
|
||||||
</display>
|
|
||||||
</class>
|
|
||||||
<interface id="3" language="java" name="com.iluwatar.CustomerDao" project="dao"
|
|
||||||
file="/dao/src/main/java/com/iluwatar/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
|
|
||||||
<position height="-1" width="-1" x="536" y="131"/>
|
|
||||||
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
sort-features="false" accessors="true" visibility="true">
|
sort-features="false" accessors="true" visibility="true">
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
</display>
|
</display>
|
||||||
</interface>
|
</interface>
|
||||||
<realization id="4">
|
<class id="3" language="java" name="com.iluwatar.dao.InMemoryCustomerDao" project="dao"
|
||||||
<end type="SOURCE" refId="2"/>
|
file="/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
|
||||||
<end type="TARGET" refId="3"/>
|
<position height="-1" width="-1" x="289" y="455"/>
|
||||||
</realization>
|
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
<association id="5">
|
sort-features="false" accessors="true" visibility="true">
|
||||||
<end type="SOURCE" refId="2" navigable="false">
|
<attributes public="true" package="true" protected="true" private="false" static="true"/>
|
||||||
<attribute id="6" name="customers"/>
|
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
<multiplicity id="7" minimum="0" maximum="2147483647"/>
|
</display>
|
||||||
|
</class>
|
||||||
|
<class id="4" language="java" name="com.iluwatar.dao.DBCustomerDao" project="dao"
|
||||||
|
file="/dao/src/main/java/com/iluwatar/dao/DBCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
|
||||||
|
<position height="-1" width="-1" x="751" y="456"/>
|
||||||
|
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
|
sort-features="false" accessors="true" visibility="true">
|
||||||
|
<attributes public="true" package="true" protected="true" private="false" static="true"/>
|
||||||
|
<operations public="true" package="true" protected="true" private="false" static="true"/>
|
||||||
|
</display>
|
||||||
|
</class>
|
||||||
|
<interface id="5" language="java" name="javax.sql.DataSource" project="dao"
|
||||||
|
file="/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
|
||||||
|
<position height="-1" width="-1" x="1083" y="459"/>
|
||||||
|
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
|
sort-features="false" accessors="true" visibility="true">
|
||||||
|
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
</display>
|
||||||
|
</interface>
|
||||||
|
<association id="6">
|
||||||
|
<end type="SOURCE" refId="4" navigable="false">
|
||||||
|
<attribute id="7" name="dataSource"/>
|
||||||
|
<multiplicity id="8" minimum="0" maximum="1"/>
|
||||||
</end>
|
</end>
|
||||||
<end type="TARGET" refId="1" navigable="true"/>
|
<end type="TARGET" refId="5" navigable="true"/>
|
||||||
<display labels="true" multiplicity="true"/>
|
<display labels="true" multiplicity="true"/>
|
||||||
</association>
|
</association>
|
||||||
|
<realization id="9">
|
||||||
|
<end type="SOURCE" refId="3"/>
|
||||||
|
<end type="TARGET" refId="2"/>
|
||||||
|
</realization>
|
||||||
|
<dependency id="10">
|
||||||
|
<end type="SOURCE" refId="1"/>
|
||||||
|
<end type="TARGET" refId="2"/>
|
||||||
|
</dependency>
|
||||||
|
<realization id="11">
|
||||||
|
<end type="SOURCE" refId="4"/>
|
||||||
|
<end type="TARGET" refId="2"/>
|
||||||
|
</realization>
|
||||||
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
sort-features="false" accessors="true" visibility="true">
|
sort-features="false" accessors="true" visibility="true">
|
||||||
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.bechte.junit</groupId>
|
<groupId>de.bechte.junit</groupId>
|
||||||
|
@ -20,31 +20,39 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.iluwatar.dao;
|
package com.iluwatar.dao;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
import org.h2.jdbcx.JdbcDataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Data Access Object (DAO) is an object that provides an abstract interface to some type of
|
* Data Access Object (DAO) is an object that provides an abstract interface to some type of
|
||||||
* database or other persistence mechanism. By mapping application calls to the persistence layer,
|
* database or other persistence mechanism. By mapping application calls to the persistence layer,
|
||||||
* DAO provide some specific data operations without exposing details of the database. This
|
* DAO provide some specific data operations without exposing details of the database. This
|
||||||
* isolation supports the Single responsibility principle. It separates what data accesses the
|
* isolation supports the Single responsibility principle. It separates what data accesses the
|
||||||
* application needs, in terms of domain-specific objects and data types (the public interface of
|
* application needs, in terms of domain-specific objects and data types (the public interface of
|
||||||
* the DAO), from how these needs can be satisfied with a specific DBMS.
|
* the DAO), from how these needs can be satisfied with a specific DBMS.
|
||||||
* <p>
|
*
|
||||||
* With the DAO pattern, we can use various method calls to retrieve/add/delete/update data without
|
* <p>With the DAO pattern, we can use various method calls to retrieve/add/delete/update data
|
||||||
* directly interacting with the data. The below example demonstrates basic CRUD operations: select,
|
* without directly interacting with the data source. The below example demonstrates basic CRUD
|
||||||
* add, update, and delete.
|
* operations: select, add, update, and delete.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class App {
|
public class App {
|
||||||
|
private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
|
||||||
private static Logger log = Logger.getLogger(App.class);
|
private static Logger log = Logger.getLogger(App.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Program entry point.
|
* Program entry point.
|
||||||
*
|
*
|
||||||
@ -52,17 +60,54 @@ public class App {
|
|||||||
* @throws Exception if any error occurs.
|
* @throws Exception if any error occurs.
|
||||||
*/
|
*/
|
||||||
public static void main(final String[] args) throws Exception {
|
public static void main(final String[] args) throws Exception {
|
||||||
final CustomerDao customerDao = new InMemoryCustomerDao();
|
final CustomerDao inMemoryDao = new InMemoryCustomerDao();
|
||||||
|
performOperationsUsing(inMemoryDao);
|
||||||
|
|
||||||
|
final DataSource dataSource = createDataSource();
|
||||||
|
createSchema(dataSource);
|
||||||
|
final CustomerDao dbDao = new DbCustomerDao(dataSource);
|
||||||
|
performOperationsUsing(dbDao);
|
||||||
|
deleteSchema(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void deleteSchema(DataSource dataSource) throws SQLException {
|
||||||
|
try (Connection connection = dataSource.getConnection();
|
||||||
|
Statement statement = connection.createStatement()) {
|
||||||
|
statement.execute("DROP TABLE CUSTOMERS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createSchema(DataSource dataSource) throws SQLException {
|
||||||
|
try (Connection connection = dataSource.getConnection();
|
||||||
|
Statement statement = connection.createStatement()) {
|
||||||
|
statement.execute("CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100), "
|
||||||
|
+ "LNAME VARCHAR(100))");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DataSource createDataSource() {
|
||||||
|
JdbcDataSource dataSource = new JdbcDataSource();
|
||||||
|
dataSource.setURL(DB_URL);
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void performOperationsUsing(final CustomerDao customerDao) throws Exception {
|
||||||
addCustomers(customerDao);
|
addCustomers(customerDao);
|
||||||
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
|
log.info("customerDao.getAllCustomers(): ");
|
||||||
log.info("customerDao.getCusterById(2): " + customerDao.getById(2));
|
try (Stream<Customer> customerStream = customerDao.getAll()) {
|
||||||
|
customerStream.forEach((customer) -> log.info(customer));
|
||||||
|
}
|
||||||
|
log.info("customerDao.getCustomerById(2): " + customerDao.getById(2));
|
||||||
final Customer customer = new Customer(4, "Dan", "Danson");
|
final Customer customer = new Customer(4, "Dan", "Danson");
|
||||||
customerDao.add(customer);
|
customerDao.add(customer);
|
||||||
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
|
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
|
||||||
customer.setFirstName("Daniel");
|
customer.setFirstName("Daniel");
|
||||||
customer.setLastName("Danielson");
|
customer.setLastName("Danielson");
|
||||||
customerDao.update(customer);
|
customerDao.update(customer);
|
||||||
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
|
log.info("customerDao.getAllCustomers(): ");
|
||||||
|
try (Stream<Customer> customerStream = customerDao.getAll()) {
|
||||||
|
customerStream.forEach((cust) -> log.info(cust));
|
||||||
|
}
|
||||||
customerDao.delete(customer);
|
customerDao.delete(customer);
|
||||||
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
|
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,11 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.iluwatar.dao;
|
package com.iluwatar.dao;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* A customer POJO that represents the data that will be read from the data source.
|
||||||
* Customer
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Customer {
|
public class Customer {
|
||||||
@ -34,7 +34,7 @@ public class Customer {
|
|||||||
private String lastName;
|
private String lastName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Creates an instance of customer.
|
||||||
*/
|
*/
|
||||||
public Customer(final int id, final String firstName, final String lastName) {
|
public Customer(final int id, final String firstName, final String lastName) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@ -73,12 +73,12 @@ public class Customer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object o) {
|
public boolean equals(final Object that) {
|
||||||
boolean isEqual = false;
|
boolean isEqual = false;
|
||||||
if (this == o) {
|
if (this == that) {
|
||||||
isEqual = true;
|
isEqual = true;
|
||||||
} else if (o != null && getClass() == o.getClass()) {
|
} else if (that != null && getClass() == that.getClass()) {
|
||||||
final Customer customer = (Customer) o;
|
final Customer customer = (Customer) that;
|
||||||
if (getId() == customer.getId()) {
|
if (getId() == customer.getId()) {
|
||||||
isEqual = true;
|
isEqual = true;
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.iluwatar.dao;
|
package com.iluwatar.dao;
|
||||||
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* In an application the Data Access Object (DAO) is a part of Data access layer. It is an object
|
* In an application the Data Access Object (DAO) is a part of Data access layer. It is an object
|
||||||
* that provides an interface to some type of persistence mechanism. By mapping application calls
|
* that provides an interface to some type of persistence mechanism. By mapping application calls
|
||||||
* to the persistence layer, DAO provides some specific data operations without exposing details
|
* to the persistence layer, DAO provides some specific data operations without exposing details
|
||||||
@ -33,25 +33,25 @@ import java.util.stream.Stream;
|
|||||||
* data accesses the application needs, in terms of domain-specific objects and data types
|
* data accesses the application needs, in terms of domain-specific objects and data types
|
||||||
* (the public interface of the DAO), from how these needs can be satisfied with a specific DBMS,
|
* (the public interface of the DAO), from how these needs can be satisfied with a specific DBMS,
|
||||||
* database schema, etc.
|
* database schema, etc.
|
||||||
* <br/><br/>
|
*
|
||||||
* Any change in the way data is stored and retrieved will not change the client code as the client
|
* <p>Any change in the way data is stored and retrieved will not change the client code as the
|
||||||
* will be using interface and need not worry about exact source.
|
* client will be using interface and need not worry about exact source.
|
||||||
*
|
*
|
||||||
* @see InMemoryCustomerDao
|
* @see InMemoryCustomerDao
|
||||||
* @see DBCustomerDao
|
* @see DbCustomerDao
|
||||||
*/
|
*/
|
||||||
public interface CustomerDao {
|
public interface CustomerDao {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return all the customers as a stream. The stream may be lazily or eagerly evaluated based on the
|
* @return all the customers as a stream. The stream may be lazily or eagerly evaluated based
|
||||||
* implementation. The stream must be closed after use.
|
* on the implementation. The stream must be closed after use.
|
||||||
* @throws Exception if any error occurs.
|
* @throws Exception if any error occurs.
|
||||||
*/
|
*/
|
||||||
Stream<Customer> getAll() throws Exception;
|
Stream<Customer> getAll() throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id unique identifier of the customer.
|
* @param id unique identifier of the customer.
|
||||||
* @return customer with unique identifier <code>id</code> is found, null otherwise.
|
* @return customer with unique identifier <code>id</code> if found, null otherwise.
|
||||||
* @throws Exception if any error occurs.
|
* @throws Exception if any error occurs.
|
||||||
*/
|
*/
|
||||||
Customer getById(int id) throws Exception;
|
Customer getById(int id) throws Exception;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.iluwatar.dao;
|
package com.iluwatar.dao;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
@ -35,27 +36,39 @@ import java.util.stream.StreamSupport;
|
|||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* An implementation of {@link CustomerDao} that persists customers in RDBMS.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DBCustomerDao implements CustomerDao {
|
public class DbCustomerDao implements CustomerDao {
|
||||||
|
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
|
|
||||||
public DBCustomerDao(DataSource dataSource) {
|
/**
|
||||||
|
* Creates an instance of {@link DbCustomerDao} which uses provided <code>dataSource</code>
|
||||||
|
* to store and retrieve customer information.
|
||||||
|
*
|
||||||
|
* @param dataSource a non-null dataSource.
|
||||||
|
*/
|
||||||
|
public DbCustomerDao(DataSource dataSource) {
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a lazily populated stream of customers. Note the stream returned must be closed to
|
||||||
|
* free all the acquired resources. The stream keeps an open connection to the database till
|
||||||
|
* it is complete or is closed manually.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Stream<Customer> getAll() throws Exception {
|
public Stream<Customer> getAll() throws Exception {
|
||||||
|
|
||||||
Connection connection;
|
Connection connection;
|
||||||
try {
|
try {
|
||||||
connection = getConnection();
|
connection = getConnection();
|
||||||
PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS");
|
PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS");
|
||||||
ResultSet resultSet = statement.executeQuery();
|
ResultSet resultSet = statement.executeQuery();
|
||||||
return StreamSupport.stream(new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE, Spliterator.ORDERED) {
|
return StreamSupport.stream(new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE,
|
||||||
|
Spliterator.ORDERED) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tryAdvance(Consumer<? super Customer> action) {
|
public boolean tryAdvance(Consumer<? super Customer> action) {
|
||||||
try {
|
try {
|
||||||
@ -65,15 +78,15 @@ public class DBCustomerDao implements CustomerDao {
|
|||||||
action.accept(createCustomer(resultSet));
|
action.accept(createCustomer(resultSet));
|
||||||
return true;
|
return true;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
throw new RuntimeException(e);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}}, false).onClose(() -> mutedClose(connection));
|
}
|
||||||
|
}, false).onClose(() -> mutedClose(connection));
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new Exception(e.getMessage(), e);
|
throw new Exception(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Connection getConnection() throws SQLException {
|
private Connection getConnection() throws SQLException {
|
||||||
return dataSource.getConnection();
|
return dataSource.getConnection();
|
||||||
}
|
}
|
||||||
@ -91,31 +104,40 @@ public class DBCustomerDao implements CustomerDao {
|
|||||||
resultSet.getString("FNAME"),
|
resultSet.getString("FNAME"),
|
||||||
resultSet.getString("LNAME"));
|
resultSet.getString("LNAME"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Customer getById(int id) throws Exception {
|
public Customer getById(int id) throws Exception {
|
||||||
try (Connection connection = getConnection();
|
try (Connection connection = getConnection();
|
||||||
PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) {
|
PreparedStatement statement =
|
||||||
statement.setInt(1, id);
|
connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) {
|
||||||
ResultSet resultSet = statement.executeQuery();
|
|
||||||
if (resultSet.next()) {
|
statement.setInt(1, id);
|
||||||
return createCustomer(resultSet);
|
ResultSet resultSet = statement.executeQuery();
|
||||||
} else {
|
if (resultSet.next()) {
|
||||||
return null;
|
return createCustomer(resultSet);
|
||||||
}
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
throw new Exception(ex.getMessage(), ex);
|
throw new Exception(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean add(Customer customer) throws Exception {
|
public boolean add(Customer customer) throws Exception {
|
||||||
if (getById(customer.getId()) != null) {
|
if (getById(customer.getId()) != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Connection connection = getConnection();
|
try (Connection connection = getConnection();
|
||||||
PreparedStatement statement = connection.prepareStatement("INSERT INTO CUSTOMERS VALUES (?,?,?)")) {
|
PreparedStatement statement =
|
||||||
|
connection.prepareStatement("INSERT INTO CUSTOMERS VALUES (?,?,?)")) {
|
||||||
statement.setInt(1, customer.getId());
|
statement.setInt(1, customer.getId());
|
||||||
statement.setString(2, customer.getFirstName());
|
statement.setString(2, customer.getFirstName());
|
||||||
statement.setString(3, customer.getLastName());
|
statement.setString(3, customer.getLastName());
|
||||||
@ -126,10 +148,14 @@ public class DBCustomerDao implements CustomerDao {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean update(Customer customer) throws Exception {
|
public boolean update(Customer customer) throws Exception {
|
||||||
try (Connection connection = getConnection();
|
try (Connection connection = getConnection();
|
||||||
PreparedStatement statement = connection.prepareStatement("UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?")) {
|
PreparedStatement statement =
|
||||||
|
connection.prepareStatement("UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?")) {
|
||||||
statement.setString(1, customer.getFirstName());
|
statement.setString(1, customer.getFirstName());
|
||||||
statement.setString(2, customer.getLastName());
|
statement.setString(2, customer.getLastName());
|
||||||
statement.setInt(3, customer.getId());
|
statement.setInt(3, customer.getId());
|
||||||
@ -139,10 +165,14 @@ public class DBCustomerDao implements CustomerDao {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean delete(Customer customer) throws Exception {
|
public boolean delete(Customer customer) throws Exception {
|
||||||
try (Connection connection = getConnection();
|
try (Connection connection = getConnection();
|
||||||
PreparedStatement statement = connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) {
|
PreparedStatement statement =
|
||||||
|
connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) {
|
||||||
statement.setInt(1, customer.getId());
|
statement.setInt(1, customer.getId());
|
||||||
return statement.executeUpdate() > 0;
|
return statement.executeUpdate() > 0;
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
@ -20,6 +20,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.iluwatar.dao;
|
package com.iluwatar.dao;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.iluwatar.dao;
|
package com.iluwatar.dao;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.iluwatar.dao;
|
package com.iluwatar.dao;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -28,33 +28,51 @@ import org.mockito.Mockito;
|
|||||||
|
|
||||||
import de.bechte.junit.runners.context.HierarchicalContextRunner;
|
import de.bechte.junit.runners.context.HierarchicalContextRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@link DbCustomerDao}.
|
||||||
|
*/
|
||||||
@RunWith(HierarchicalContextRunner.class)
|
@RunWith(HierarchicalContextRunner.class)
|
||||||
public class DBCustomerDaoTest {
|
public class DbCustomerDaoTest {
|
||||||
|
|
||||||
private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
|
private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
|
||||||
private DBCustomerDao dao;
|
private DbCustomerDao dao;
|
||||||
private Customer existingCustomer = new Customer(1, "Freddy", "Krueger");
|
private Customer existingCustomer = new Customer(1, "Freddy", "Krueger");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates customers schema.
|
||||||
|
* @throws SQLException if there is any error while creating schema.
|
||||||
|
*/
|
||||||
@Before
|
@Before
|
||||||
public void createSchema() throws SQLException {
|
public void createSchema() throws SQLException {
|
||||||
try (Connection connection = DriverManager.getConnection(DB_URL);
|
try (Connection connection = DriverManager.getConnection(DB_URL);
|
||||||
Statement statement = connection.createStatement()) {
|
Statement statement = connection.createStatement()) {
|
||||||
statement.execute("CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100), LNAME VARCHAR(100))");
|
statement.execute("CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100),"
|
||||||
|
+ " LNAME VARCHAR(100))");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the scenario where DB connectivity is present.
|
||||||
|
*/
|
||||||
public class ConnectionSuccess {
|
public class ConnectionSuccess {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup for connection success scenario.
|
||||||
|
* @throws Exception if any error occurs.
|
||||||
|
*/
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
JdbcDataSource dataSource = new JdbcDataSource();
|
JdbcDataSource dataSource = new JdbcDataSource();
|
||||||
dataSource.setURL(DB_URL);
|
dataSource.setURL(DB_URL);
|
||||||
dao = new DBCustomerDao(dataSource);
|
dao = new DbCustomerDao(dataSource);
|
||||||
boolean result = dao.add(existingCustomer);
|
boolean result = dao.add(existingCustomer);
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NonExistantCustomer {
|
/**
|
||||||
|
* Represents the scenario when DAO operations are being performed on a non existing customer.
|
||||||
|
*/
|
||||||
|
public class NonExistingCustomer {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addingShouldResultInSuccess() throws Exception {
|
public void addingShouldResultInSuccess() throws Exception {
|
||||||
@ -97,6 +115,11 @@ public class DBCustomerDaoTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a scenario where DAO operations are being performed on an already existing
|
||||||
|
* customer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class ExistingCustomer {
|
public class ExistingCustomer {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -135,14 +158,23 @@ public class DBCustomerDaoTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DBConnectivityIssue {
|
/**
|
||||||
|
* Represents a scenario where DB connectivity is not present due to network issue, or
|
||||||
|
* DB service unavailable.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ConnectivityIssue {
|
||||||
|
|
||||||
private static final String EXCEPTION_CAUSE = "Connection not available";
|
private static final String EXCEPTION_CAUSE = "Connection not available";
|
||||||
@Rule public ExpectedException exception = ExpectedException.none();
|
@Rule public ExpectedException exception = ExpectedException.none();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setup a connection failure scenario.
|
||||||
|
* @throws SQLException if any error occurs.
|
||||||
|
*/
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws SQLException {
|
public void setUp() throws SQLException {
|
||||||
dao = new DBCustomerDao(mockedDatasource());
|
dao = new DbCustomerDao(mockedDatasource());
|
||||||
exception.expect(Exception.class);
|
exception.expect(Exception.class);
|
||||||
exception.expectMessage(EXCEPTION_CAUSE);
|
exception.expectMessage(EXCEPTION_CAUSE);
|
||||||
}
|
}
|
||||||
@ -186,6 +218,10 @@ public class DBCustomerDaoTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete customer schema for fresh setup per test.
|
||||||
|
* @throws SQLException if any error occurs.
|
||||||
|
*/
|
||||||
@After
|
@After
|
||||||
public void deleteSchema() throws SQLException {
|
public void deleteSchema() throws SQLException {
|
||||||
try (Connection connection = DriverManager.getConnection(DB_URL);
|
try (Connection connection = DriverManager.getConnection(DB_URL);
|
@ -20,6 +20,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.iluwatar.dao;
|
package com.iluwatar.dao;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@ -36,6 +37,9 @@ import org.junit.runner.RunWith;
|
|||||||
|
|
||||||
import de.bechte.junit.runners.context.HierarchicalContextRunner;
|
import de.bechte.junit.runners.context.HierarchicalContextRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@link InMemoryCustomerDao}.
|
||||||
|
*/
|
||||||
@RunWith(HierarchicalContextRunner.class)
|
@RunWith(HierarchicalContextRunner.class)
|
||||||
public class InMemoryCustomerDaoTest {
|
public class InMemoryCustomerDaoTest {
|
||||||
|
|
||||||
@ -47,8 +51,12 @@ public class InMemoryCustomerDaoTest {
|
|||||||
dao = new InMemoryCustomerDao();
|
dao = new InMemoryCustomerDao();
|
||||||
dao.add(CUSTOMER);
|
dao.add(CUSTOMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NonExistantCustomer {
|
/**
|
||||||
|
* Represents the scenario when the DAO operations are being performed on a non existent
|
||||||
|
* customer.
|
||||||
|
*/
|
||||||
|
public class NonExistingCustomer {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addingShouldResultInSuccess() throws Exception {
|
public void addingShouldResultInSuccess() throws Exception {
|
||||||
@ -91,6 +99,10 @@ public class InMemoryCustomerDaoTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the scenario when the DAO operations are being performed on an already existing
|
||||||
|
* customer.
|
||||||
|
*/
|
||||||
public class ExistingCustomer {
|
public class ExistingCustomer {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user