Merge pull request #407 from iluwatar/refactor-dao
Solves #404 Refactor dao
This commit is contained in:
		
							
								
								
									
										
											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"?>
 | 
			
		||||
<class-diagram version="1.1.8" icons="true" always-add-relationships="false" generalizations="true" realizations="true" 
 | 
			
		||||
  associations="true" dependencies="false" nesting-relationships="true">  
 | 
			
		||||
  <class id="1" language="java" name="com.iluwatar.Customer" project="dao" 
 | 
			
		||||
    file="/dao/src/main/java/com/iluwatar/Customer.java" binary="false" corner="BOTTOM_RIGHT">    
 | 
			
		||||
    <position height="-1" width="-1" x="176" y="337"/>    
 | 
			
		||||
  <class id="1" language="java" name="com.iluwatar.dao.App" project="dao" 
 | 
			
		||||
    file="/dao/src/main/java/com/iluwatar/dao/App.java" binary="false" corner="BOTTOM_RIGHT">    
 | 
			
		||||
    <position height="-1" width="-1" x="910" y="191"/>    
 | 
			
		||||
    <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"/>    
 | 
			
		||||
      <attributes public="true" package="true" protected="true" private="false" static="true"/>      
 | 
			
		||||
      <operations public="true" package="true" protected="true" private="false" static="true"/>    
 | 
			
		||||
    </display>  
 | 
			
		||||
  </class>  
 | 
			
		||||
  <class id="2" language="java" name="com.iluwatar.CustomerDaoImpl" project="dao" 
 | 
			
		||||
    file="/dao/src/main/java/com/iluwatar/CustomerDaoImpl.java" binary="false" corner="BOTTOM_RIGHT">    
 | 
			
		||||
    <position height="-1" width="-1" x="540" y="334"/>    
 | 
			
		||||
    <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"/>    
 | 
			
		||||
  <interface id="2" language="java" name="com.iluwatar.dao.CustomerDao" project="dao" 
 | 
			
		||||
    file="/dao/src/main/java/com/iluwatar/dao/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">    
 | 
			
		||||
    <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>  
 | 
			
		||||
  </interface>  
 | 
			
		||||
  <realization id="4">    
 | 
			
		||||
    <end type="SOURCE" refId="2"/>    
 | 
			
		||||
    <end type="TARGET" refId="3"/>  
 | 
			
		||||
  </realization>  
 | 
			
		||||
  <association id="5">    
 | 
			
		||||
    <end type="SOURCE" refId="2" navigable="false">      
 | 
			
		||||
      <attribute id="6" name="customers"/>      
 | 
			
		||||
      <multiplicity id="7" minimum="0" maximum="2147483647"/>    
 | 
			
		||||
  <class id="3" language="java" name="com.iluwatar.dao.InMemoryCustomerDao" project="dao" 
 | 
			
		||||
    file="/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">    
 | 
			
		||||
    <position height="-1" width="-1" x="289" y="455"/>    
 | 
			
		||||
    <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="true" static="true"/>    
 | 
			
		||||
    </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 type="TARGET" refId="1" navigable="true"/>    
 | 
			
		||||
    <end type="TARGET" refId="5" navigable="true"/>    
 | 
			
		||||
    <display labels="true" multiplicity="true"/>  
 | 
			
		||||
  </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" 
 | 
			
		||||
    sort-features="false" accessors="true" visibility="true">    
 | 
			
		||||
    <attributes public="true" package="true" protected="true" private="true" static="true"/>    
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								dao/pom.xml
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								dao/pom.xml
									
									
									
									
									
								
							@@ -44,6 +44,18 @@
 | 
			
		||||
      <groupId>log4j</groupId>
 | 
			
		||||
      <artifactId>log4j</artifactId>
 | 
			
		||||
    </dependency>
 | 
			
		||||
    <dependency>
 | 
			
		||||
        <groupId>com.h2database</groupId>
 | 
			
		||||
        <artifactId>h2</artifactId>
 | 
			
		||||
      </dependency>
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>de.bechte.junit</groupId>
 | 
			
		||||
      <artifactId>junit-hierarchicalcontextrunner</artifactId>
 | 
			
		||||
    </dependency>
 | 
			
		||||
    <dependency>
 | 
			
		||||
        <groupId>org.mockito</groupId>
 | 
			
		||||
        <artifactId>mockito-core</artifactId>
 | 
			
		||||
    </dependency>
 | 
			
		||||
  </dependencies>
 | 
			
		||||
 | 
			
		||||
  <build>
 | 
			
		||||
 
 | 
			
		||||
@@ -20,49 +20,101 @@
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
import java.sql.Connection;
 | 
			
		||||
import java.sql.SQLException;
 | 
			
		||||
import java.sql.Statement;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
import javax.sql.DataSource;
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 * 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
 | 
			
		||||
 * 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
 | 
			
		||||
 * 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
 | 
			
		||||
 * directly interacting with the data. The below example demonstrates basic CRUD operations: select,
 | 
			
		||||
 * add, update, and delete.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>With the DAO pattern, we can use various method calls to retrieve/add/delete/update data 
 | 
			
		||||
 * without directly interacting with the data source. The below example demonstrates basic CRUD 
 | 
			
		||||
 * operations: select, add, update, and delete.
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
public class App {
 | 
			
		||||
 | 
			
		||||
  private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
 | 
			
		||||
  private static Logger log = Logger.getLogger(App.class);
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  /**
 | 
			
		||||
   * Program entry point.
 | 
			
		||||
   * 
 | 
			
		||||
   * @param args command line args.
 | 
			
		||||
   * @throws Exception if any error occurs. 
 | 
			
		||||
   */
 | 
			
		||||
  public static void main(final String[] args) {
 | 
			
		||||
    final CustomerDao customerDao = new CustomerDaoImpl(generateSampleCustomers());
 | 
			
		||||
    log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
 | 
			
		||||
    log.info("customerDao.getCusterById(2): " + customerDao.getCustomerById(2));
 | 
			
		||||
  public static void main(final String[] args) throws Exception {
 | 
			
		||||
    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(CustomerSchemaSql.DELETE_SCHEMA_SQL);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static void createSchema(DataSource dataSource) throws SQLException {
 | 
			
		||||
    try (Connection connection = dataSource.getConnection();
 | 
			
		||||
        Statement statement = connection.createStatement()) {
 | 
			
		||||
      statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
    log.info("customerDao.getAllCustomers(): ");
 | 
			
		||||
    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");
 | 
			
		||||
    customerDao.addCustomer(customer);
 | 
			
		||||
    log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
 | 
			
		||||
    customerDao.add(customer);
 | 
			
		||||
    log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
 | 
			
		||||
    customer.setFirstName("Daniel");
 | 
			
		||||
    customer.setLastName("Danielson");
 | 
			
		||||
    customerDao.updateCustomer(customer);
 | 
			
		||||
    log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
 | 
			
		||||
    customerDao.deleteCustomer(customer);
 | 
			
		||||
    log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
 | 
			
		||||
    customerDao.update(customer);
 | 
			
		||||
    log.info("customerDao.getAllCustomers(): ");
 | 
			
		||||
    try (Stream<Customer> customerStream = customerDao.getAll()) {
 | 
			
		||||
      customerStream.forEach((cust) -> log.info(cust));
 | 
			
		||||
    }
 | 
			
		||||
    customerDao.delete(customer);
 | 
			
		||||
    log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static void addCustomers(CustomerDao customerDao) throws Exception {
 | 
			
		||||
    for (Customer customer : generateSampleCustomers()) {
 | 
			
		||||
      customerDao.add(customer);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
 
 | 
			
		||||
@@ -20,11 +20,11 @@
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * Customer
 | 
			
		||||
 * A customer POJO that represents the data that will be read from the data source.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
public class Customer {
 | 
			
		||||
@@ -34,7 +34,7 @@ public class Customer {
 | 
			
		||||
  private String lastName;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructor
 | 
			
		||||
   * Creates an instance of customer.
 | 
			
		||||
   */
 | 
			
		||||
  public Customer(final int id, final String firstName, final String lastName) {
 | 
			
		||||
    this.id = id;
 | 
			
		||||
@@ -73,12 +73,12 @@ public class Customer {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean equals(final Object o) {
 | 
			
		||||
  public boolean equals(final Object that) {
 | 
			
		||||
    boolean isEqual = false;
 | 
			
		||||
    if (this == o) {
 | 
			
		||||
    if (this == that) {
 | 
			
		||||
      isEqual = true;
 | 
			
		||||
    } else if (o != null && getClass() == o.getClass()) {
 | 
			
		||||
      final Customer customer = (Customer) o;
 | 
			
		||||
    } else if (that != null && getClass() == that.getClass()) {
 | 
			
		||||
      final Customer customer = (Customer) that;
 | 
			
		||||
      if (getId() == customer.getId()) {
 | 
			
		||||
        isEqual = true;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,24 +20,62 @@
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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
 | 
			
		||||
 * to the persistence layer, DAO provides some specific data operations without exposing details 
 | 
			
		||||
 * of the database. This 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 the DAO), from how these needs can be satisfied with a specific DBMS,
 | 
			
		||||
 * database schema, etc.
 | 
			
		||||
 * 
 | 
			
		||||
 * CustomerDao
 | 
			
		||||
 *
 | 
			
		||||
 * <p>Any change in the way data is stored and retrieved will not change the client code as the 
 | 
			
		||||
 * client will be using interface and need not worry about exact source.
 | 
			
		||||
 * 
 | 
			
		||||
 * @see InMemoryCustomerDao
 | 
			
		||||
 * @see DbCustomerDao
 | 
			
		||||
 */
 | 
			
		||||
public interface CustomerDao {
 | 
			
		||||
 | 
			
		||||
  List<Customer> getAllCustomers();
 | 
			
		||||
  /**
 | 
			
		||||
   * @return all the customers as a stream. The stream may be lazily or eagerly evaluated based 
 | 
			
		||||
   *     on the implementation. The stream must be closed after use.
 | 
			
		||||
   * @throws Exception if any error occurs.
 | 
			
		||||
   */
 | 
			
		||||
  Stream<Customer> getAll() throws Exception;
 | 
			
		||||
  
 | 
			
		||||
  /**
 | 
			
		||||
   * @param id unique identifier of the customer.
 | 
			
		||||
   * @return an optional with customer if a customer with unique identifier <code>id</code>
 | 
			
		||||
   *     exists, empty optional otherwise.
 | 
			
		||||
   * @throws Exception if any error occurs.
 | 
			
		||||
   */
 | 
			
		||||
  Optional<Customer> getById(int id) throws Exception;
 | 
			
		||||
 | 
			
		||||
  Customer getCustomerById(int id);
 | 
			
		||||
  /**
 | 
			
		||||
   * @param customer the customer to be added.
 | 
			
		||||
   * @return true if customer is successfully added, false if customer already exists.
 | 
			
		||||
   * @throws Exception if any error occurs.
 | 
			
		||||
   */
 | 
			
		||||
  boolean add(Customer customer) throws Exception;
 | 
			
		||||
 | 
			
		||||
  void addCustomer(Customer customer);
 | 
			
		||||
  /**
 | 
			
		||||
   * @param customer the customer to be updated.
 | 
			
		||||
   * @return true if customer exists and is successfully updated, false otherwise.
 | 
			
		||||
   * @throws Exception if any error occurs.
 | 
			
		||||
   */
 | 
			
		||||
  boolean update(Customer customer) throws Exception;
 | 
			
		||||
 | 
			
		||||
  void updateCustomer(Customer customer);
 | 
			
		||||
 | 
			
		||||
  void deleteCustomer(Customer customer);
 | 
			
		||||
  /**
 | 
			
		||||
   * @param customer the customer to be deleted.
 | 
			
		||||
   * @return true if customer exists and is successfully deleted, false otherwise.
 | 
			
		||||
   * @throws Exception if any error occurs.
 | 
			
		||||
   */
 | 
			
		||||
  boolean delete(Customer customer) throws Exception;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,84 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * The MIT License
 | 
			
		||||
 * Copyright (c) 2014 Ilkka Seppälä
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * The 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,
 | 
			
		||||
 * 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
 | 
			
		||||
 * 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, database schema, etc.
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
public class CustomerDaoImpl implements CustomerDao {
 | 
			
		||||
 | 
			
		||||
  // Represents the DB structure for our example so we don't have to managed it ourselves
 | 
			
		||||
  // Note: Normally this would be in the form of an actual database and not part of the Dao Impl.
 | 
			
		||||
  private List<Customer> customers;
 | 
			
		||||
 | 
			
		||||
  public CustomerDaoImpl(final List<Customer> customers) {
 | 
			
		||||
    this.customers = customers;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public List<Customer> getAllCustomers() {
 | 
			
		||||
    return customers;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Customer getCustomerById(final int id) {
 | 
			
		||||
    Customer customer = null;
 | 
			
		||||
    for (final Customer cus : getAllCustomers()) {
 | 
			
		||||
      if (cus.getId() == id) {
 | 
			
		||||
        customer = cus;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return customer;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void addCustomer(final Customer customer) {
 | 
			
		||||
    if (getCustomerById(customer.getId()) == null) {
 | 
			
		||||
      customers.add(customer);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void updateCustomer(final Customer customer) {
 | 
			
		||||
    if (getAllCustomers().contains(customer)) {
 | 
			
		||||
      final int index = getAllCustomers().indexOf(customer);
 | 
			
		||||
      getAllCustomers().set(index, customer);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void deleteCustomer(final Customer customer) {
 | 
			
		||||
    getAllCustomers().remove(customer);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
public interface CustomerSchemaSql {
 | 
			
		||||
 | 
			
		||||
  String CREATE_SCHEMA_SQL = "CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100), " 
 | 
			
		||||
      + "LNAME VARCHAR(100))";
 | 
			
		||||
  
 | 
			
		||||
  String DELETE_SCHEMA_SQL = "DROP TABLE CUSTOMERS";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										183
									
								
								dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,183 @@
 | 
			
		||||
/**
 | 
			
		||||
 * The MIT License
 | 
			
		||||
 * Copyright (c) 2014 Ilkka Seppälä
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
import java.sql.Connection;
 | 
			
		||||
import java.sql.PreparedStatement;
 | 
			
		||||
import java.sql.ResultSet;
 | 
			
		||||
import java.sql.SQLException;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.Spliterator;
 | 
			
		||||
import java.util.Spliterators;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
import java.util.stream.StreamSupport;
 | 
			
		||||
 | 
			
		||||
import javax.sql.DataSource;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An implementation of {@link CustomerDao} that persists customers in RDBMS. 
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
public class DbCustomerDao implements CustomerDao {
 | 
			
		||||
 | 
			
		||||
  private final 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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @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
 | 
			
		||||
  public Stream<Customer> getAll() throws Exception {
 | 
			
		||||
 | 
			
		||||
    Connection connection;
 | 
			
		||||
    try {
 | 
			
		||||
      connection = getConnection();
 | 
			
		||||
      PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS");
 | 
			
		||||
      ResultSet resultSet = statement.executeQuery();
 | 
			
		||||
      return StreamSupport.stream(new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE, 
 | 
			
		||||
          Spliterator.ORDERED) {
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public boolean tryAdvance(Consumer<? super Customer> action) {
 | 
			
		||||
          try {
 | 
			
		||||
            if (!resultSet.next()) {
 | 
			
		||||
              return false;
 | 
			
		||||
            }
 | 
			
		||||
            action.accept(createCustomer(resultSet));
 | 
			
		||||
            return true;
 | 
			
		||||
          } catch (SQLException e) {
 | 
			
		||||
            throw new RuntimeException(e);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }, false).onClose(() -> mutedClose(connection));
 | 
			
		||||
    } catch (SQLException e) {
 | 
			
		||||
      throw new Exception(e.getMessage(), e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Connection getConnection() throws SQLException {
 | 
			
		||||
    return dataSource.getConnection();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void mutedClose(Connection connection) {
 | 
			
		||||
    try {
 | 
			
		||||
      connection.close();
 | 
			
		||||
    } catch (SQLException e) {
 | 
			
		||||
      e.printStackTrace();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Customer createCustomer(ResultSet resultSet) throws SQLException {
 | 
			
		||||
    return new Customer(resultSet.getInt("ID"), 
 | 
			
		||||
        resultSet.getString("FNAME"), 
 | 
			
		||||
        resultSet.getString("LNAME"));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritDoc}
 | 
			
		||||
   */
 | 
			
		||||
  @Override
 | 
			
		||||
  public Optional<Customer> getById(int id) throws Exception {
 | 
			
		||||
    try (Connection connection = getConnection();
 | 
			
		||||
        PreparedStatement statement = 
 | 
			
		||||
            connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) {
 | 
			
		||||
 | 
			
		||||
      statement.setInt(1, id);
 | 
			
		||||
      ResultSet resultSet = statement.executeQuery();
 | 
			
		||||
      if (resultSet.next()) {
 | 
			
		||||
        return Optional.of(createCustomer(resultSet));
 | 
			
		||||
      } else {
 | 
			
		||||
        return Optional.empty();
 | 
			
		||||
      }
 | 
			
		||||
    } catch (SQLException ex) {
 | 
			
		||||
      throw new Exception(ex.getMessage(), ex);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritDoc}
 | 
			
		||||
   */
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean add(Customer customer) throws Exception {
 | 
			
		||||
    if (getById(customer.getId()).isPresent()) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try (Connection connection = getConnection();
 | 
			
		||||
        PreparedStatement statement = 
 | 
			
		||||
            connection.prepareStatement("INSERT INTO CUSTOMERS VALUES (?,?,?)")) {
 | 
			
		||||
      statement.setInt(1, customer.getId());
 | 
			
		||||
      statement.setString(2, customer.getFirstName());
 | 
			
		||||
      statement.setString(3, customer.getLastName());
 | 
			
		||||
      statement.execute();
 | 
			
		||||
      return true;
 | 
			
		||||
    } catch (SQLException ex) {
 | 
			
		||||
      throw new Exception(ex.getMessage(), ex);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritDoc}
 | 
			
		||||
   */
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean update(Customer customer) throws Exception {
 | 
			
		||||
    try (Connection connection = getConnection();
 | 
			
		||||
        PreparedStatement statement = 
 | 
			
		||||
            connection.prepareStatement("UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?")) {
 | 
			
		||||
      statement.setString(1, customer.getFirstName());
 | 
			
		||||
      statement.setString(2, customer.getLastName());
 | 
			
		||||
      statement.setInt(3, customer.getId());
 | 
			
		||||
      return statement.executeUpdate() > 0;
 | 
			
		||||
    } catch (SQLException ex) {
 | 
			
		||||
      throw new Exception(ex.getMessage(), ex);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritDoc}
 | 
			
		||||
   */
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean delete(Customer customer) throws Exception {
 | 
			
		||||
    try (Connection connection = getConnection();
 | 
			
		||||
        PreparedStatement statement = 
 | 
			
		||||
            connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) {
 | 
			
		||||
      statement.setInt(1, customer.getId());
 | 
			
		||||
      return statement.executeUpdate() > 0;
 | 
			
		||||
    } catch (SQLException ex) {
 | 
			
		||||
      throw new Exception(ex.getMessage(), ex);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										73
									
								
								dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
/**
 | 
			
		||||
 * The MIT License
 | 
			
		||||
 * Copyright (c) 2014 Ilkka Seppälä
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An in memory implementation of {@link CustomerDao}, which stores the customers in JVM memory
 | 
			
		||||
 * and data is lost when the application exits.
 | 
			
		||||
 * <br/>
 | 
			
		||||
 * This implementation is useful as temporary database or for testing.
 | 
			
		||||
 */
 | 
			
		||||
public class InMemoryCustomerDao implements CustomerDao {
 | 
			
		||||
 | 
			
		||||
  private Map<Integer, Customer> idToCustomer = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * An eagerly evaluated stream of customers stored in memory.
 | 
			
		||||
   */
 | 
			
		||||
  @Override
 | 
			
		||||
  public Stream<Customer> getAll() {
 | 
			
		||||
    return idToCustomer.values().stream();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Optional<Customer> getById(final int id) {
 | 
			
		||||
    return Optional.ofNullable(idToCustomer.get(id));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean add(final Customer customer) {
 | 
			
		||||
    if (getById(customer.getId()).isPresent()) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    idToCustomer.put(customer.getId(), customer);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean update(final Customer customer) {
 | 
			
		||||
    return idToCustomer.replace(customer.getId(), customer) != null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean delete(final Customer customer) {
 | 
			
		||||
    return idToCustomer.remove(customer.getId()) != null;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -20,18 +20,17 @@
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests that DAO example runs without errors.
 | 
			
		||||
 */
 | 
			
		||||
public class AppTest {
 | 
			
		||||
  @Test
 | 
			
		||||
  public void test() throws IOException {
 | 
			
		||||
  public void test() throws Exception {
 | 
			
		||||
    String[] args = {};
 | 
			
		||||
    App.main(args);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,121 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * The MIT License
 | 
			
		||||
 * Copyright (c) 2014 Ilkka Seppälä
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
import static org.junit.Assert.assertNull;
 | 
			
		||||
import static org.junit.Assert.assertTrue;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
public class CustomerDaoImplTest {
 | 
			
		||||
 | 
			
		||||
  private CustomerDaoImpl impl;
 | 
			
		||||
  private List<Customer> customers;
 | 
			
		||||
  private static final Customer CUSTOMER = new Customer(1, "Freddy", "Krueger");
 | 
			
		||||
 | 
			
		||||
  @Before
 | 
			
		||||
  public void setUp() {
 | 
			
		||||
    customers = new ArrayList<>();
 | 
			
		||||
    customers.add(CUSTOMER);
 | 
			
		||||
    impl = new CustomerDaoImpl(customers);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void deleteExistingCustomer() {
 | 
			
		||||
    assertEquals(1, impl.getAllCustomers().size());
 | 
			
		||||
    impl.deleteCustomer(CUSTOMER);
 | 
			
		||||
    assertTrue(impl.getAllCustomers().isEmpty());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void deleteNonExistingCustomer() {
 | 
			
		||||
    final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
 | 
			
		||||
    impl.deleteCustomer(nonExistingCustomer);
 | 
			
		||||
    assertEquals(1, impl.getAllCustomers().size());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void updateExistingCustomer() {
 | 
			
		||||
    final String newFirstname = "Bernard";
 | 
			
		||||
    final String newLastname = "Montgomery";
 | 
			
		||||
    final Customer customer = new Customer(CUSTOMER.getId(), newFirstname, newLastname);
 | 
			
		||||
    impl.updateCustomer(customer);
 | 
			
		||||
    final Customer cust = impl.getCustomerById(CUSTOMER.getId());
 | 
			
		||||
    assertEquals(newFirstname, cust.getFirstName());
 | 
			
		||||
    assertEquals(newLastname, cust.getLastName());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void updateNonExistingCustomer() {
 | 
			
		||||
    final int nonExistingId = getNonExistingCustomerId();
 | 
			
		||||
    final String newFirstname = "Douglas";
 | 
			
		||||
    final String newLastname = "MacArthur";
 | 
			
		||||
    final Customer customer = new Customer(nonExistingId, newFirstname, newLastname);
 | 
			
		||||
    impl.updateCustomer(customer);
 | 
			
		||||
    assertNull(impl.getCustomerById(nonExistingId));
 | 
			
		||||
    final Customer existingCustomer = impl.getCustomerById(CUSTOMER.getId());
 | 
			
		||||
    assertEquals(CUSTOMER.getFirstName(), existingCustomer.getFirstName());
 | 
			
		||||
    assertEquals(CUSTOMER.getLastName(), existingCustomer.getLastName());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void addCustomer() {
 | 
			
		||||
    final Customer newCustomer = new Customer(3, "George", "Patton");
 | 
			
		||||
    impl.addCustomer(newCustomer);
 | 
			
		||||
    assertEquals(2, impl.getAllCustomers().size());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void addAlreadyAddedCustomer() {
 | 
			
		||||
    final Customer newCustomer = new Customer(3, "George", "Patton");
 | 
			
		||||
    impl.addCustomer(newCustomer);
 | 
			
		||||
    assertEquals(2, impl.getAllCustomers().size());
 | 
			
		||||
    impl.addCustomer(newCustomer);
 | 
			
		||||
    assertEquals(2, impl.getAllCustomers().size());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void getExistinCustomerById() {
 | 
			
		||||
    assertEquals(CUSTOMER, impl.getCustomerById(CUSTOMER.getId()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void getNonExistinCustomerById() {
 | 
			
		||||
    final int nonExistingId = getNonExistingCustomerId();
 | 
			
		||||
    assertNull(impl.getCustomerById(nonExistingId));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * An arbitrary number which does not correspond to an active Customer id.
 | 
			
		||||
   * 
 | 
			
		||||
   * @return an int of a customer id which doesn't exist
 | 
			
		||||
   */
 | 
			
		||||
  private int getNonExistingCustomerId() {
 | 
			
		||||
    return 999;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										247
									
								
								dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,247 @@
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
import static org.junit.Assert.assertFalse;
 | 
			
		||||
import static org.junit.Assert.assertNull;
 | 
			
		||||
import static org.junit.Assert.assertTrue;
 | 
			
		||||
import static org.junit.Assume.assumeTrue;
 | 
			
		||||
import static org.mockito.Mockito.doReturn;
 | 
			
		||||
import static org.mockito.Mockito.doThrow;
 | 
			
		||||
import static org.mockito.Mockito.mock;
 | 
			
		||||
 | 
			
		||||
import java.sql.Connection;
 | 
			
		||||
import java.sql.DriverManager;
 | 
			
		||||
import java.sql.SQLException;
 | 
			
		||||
import java.sql.Statement;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
import javax.sql.DataSource;
 | 
			
		||||
 | 
			
		||||
import org.h2.jdbcx.JdbcDataSource;
 | 
			
		||||
import org.junit.After;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Rule;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.rules.ExpectedException;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.mockito.Mockito;
 | 
			
		||||
 | 
			
		||||
import de.bechte.junit.runners.context.HierarchicalContextRunner;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests {@link DbCustomerDao}.
 | 
			
		||||
 */
 | 
			
		||||
@RunWith(HierarchicalContextRunner.class)
 | 
			
		||||
public class DbCustomerDaoTest {
 | 
			
		||||
 | 
			
		||||
  private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
 | 
			
		||||
  private DbCustomerDao dao;
 | 
			
		||||
  private Customer existingCustomer = new Customer(1, "Freddy", "Krueger");
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates customers schema.
 | 
			
		||||
   * @throws SQLException if there is any error while creating schema.
 | 
			
		||||
   */
 | 
			
		||||
  @Before
 | 
			
		||||
  public void createSchema() throws SQLException {
 | 
			
		||||
    try (Connection connection = DriverManager.getConnection(DB_URL);
 | 
			
		||||
        Statement statement = connection.createStatement()) {
 | 
			
		||||
      statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Represents the scenario where DB connectivity is present.
 | 
			
		||||
   */
 | 
			
		||||
  public class ConnectionSuccess {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Setup for connection success scenario.
 | 
			
		||||
     * @throws Exception if any error occurs.
 | 
			
		||||
     */
 | 
			
		||||
    @Before
 | 
			
		||||
    public void setUp() throws Exception {
 | 
			
		||||
      JdbcDataSource dataSource = new JdbcDataSource();
 | 
			
		||||
      dataSource.setURL(DB_URL);
 | 
			
		||||
      dao = new DbCustomerDao(dataSource);
 | 
			
		||||
      boolean result = dao.add(existingCustomer);
 | 
			
		||||
      assertTrue(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Represents the scenario when DAO operations are being performed on a non existing customer.
 | 
			
		||||
     */
 | 
			
		||||
    public class NonExistingCustomer {
 | 
			
		||||
 | 
			
		||||
      @Test
 | 
			
		||||
      public void addingShouldResultInSuccess() throws Exception {
 | 
			
		||||
        try (Stream<Customer> allCustomers = dao.getAll()) {
 | 
			
		||||
          assumeTrue(allCustomers.count() == 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
 | 
			
		||||
        boolean result = dao.add(nonExistingCustomer);
 | 
			
		||||
        assertTrue(result);
 | 
			
		||||
 | 
			
		||||
        assertCustomerCountIs(2);
 | 
			
		||||
        assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Test
 | 
			
		||||
      public void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
 | 
			
		||||
        final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
 | 
			
		||||
        boolean result = dao.delete(nonExistingCustomer);
 | 
			
		||||
 | 
			
		||||
        assertFalse(result);
 | 
			
		||||
        assertCustomerCountIs(1);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Test
 | 
			
		||||
      public void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
 | 
			
		||||
        final int nonExistingId = getNonExistingCustomerId();
 | 
			
		||||
        final String newFirstname = "Douglas";
 | 
			
		||||
        final String newLastname = "MacArthur";
 | 
			
		||||
        final Customer customer = new Customer(nonExistingId, newFirstname, newLastname);
 | 
			
		||||
        boolean result = dao.update(customer);
 | 
			
		||||
 | 
			
		||||
        assertFalse(result);
 | 
			
		||||
        assertFalse(dao.getById(nonExistingId).isPresent());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Test
 | 
			
		||||
      public void retrieveShouldReturnNoCustomer() throws Exception {
 | 
			
		||||
        assertFalse(dao.getById(getNonExistingCustomerId()).isPresent());
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Represents a scenario where DAO operations are being performed on an already existing
 | 
			
		||||
     * customer.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    public class ExistingCustomer {
 | 
			
		||||
 | 
			
		||||
      @Test
 | 
			
		||||
      public void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception {
 | 
			
		||||
        Customer existingCustomer = new Customer(1, "Freddy", "Krueger");
 | 
			
		||||
 | 
			
		||||
        boolean result = dao.add(existingCustomer);
 | 
			
		||||
 | 
			
		||||
        assertFalse(result);
 | 
			
		||||
        assertCustomerCountIs(1);
 | 
			
		||||
        assertEquals(existingCustomer, dao.getById(existingCustomer.getId()).get());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Test
 | 
			
		||||
      public void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception {
 | 
			
		||||
        boolean result = dao.delete(existingCustomer);
 | 
			
		||||
 | 
			
		||||
        assertTrue(result);
 | 
			
		||||
        assertCustomerCountIs(0);
 | 
			
		||||
        assertFalse(dao.getById(existingCustomer.getId()).isPresent());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Test
 | 
			
		||||
      public void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation() throws Exception {
 | 
			
		||||
        final String newFirstname = "Bernard";
 | 
			
		||||
        final String newLastname = "Montgomery";
 | 
			
		||||
        final Customer customer = new Customer(existingCustomer.getId(), newFirstname, newLastname);
 | 
			
		||||
        boolean result = dao.update(customer);
 | 
			
		||||
 | 
			
		||||
        assertTrue(result);
 | 
			
		||||
 | 
			
		||||
        final Customer cust = dao.getById(existingCustomer.getId()).get();
 | 
			
		||||
        assertEquals(newFirstname, cust.getFirstName());
 | 
			
		||||
        assertEquals(newLastname, cust.getLastName());
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 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";
 | 
			
		||||
    @Rule public ExpectedException exception = ExpectedException.none();
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * setup a connection failure scenario.
 | 
			
		||||
     * @throws SQLException if any error occurs.
 | 
			
		||||
     */
 | 
			
		||||
    @Before
 | 
			
		||||
    public void setUp() throws SQLException {
 | 
			
		||||
      dao = new DbCustomerDao(mockedDatasource());
 | 
			
		||||
      exception.expect(Exception.class);
 | 
			
		||||
      exception.expectMessage(EXCEPTION_CAUSE);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private DataSource mockedDatasource() throws SQLException {
 | 
			
		||||
      DataSource mockedDataSource = mock(DataSource.class);
 | 
			
		||||
      Connection mockedConnection = mock(Connection.class);
 | 
			
		||||
      SQLException exception = new SQLException(EXCEPTION_CAUSE);
 | 
			
		||||
      doThrow(exception).when(mockedConnection).prepareStatement(Mockito.anyString());
 | 
			
		||||
      doReturn(mockedConnection).when(mockedDataSource).getConnection();
 | 
			
		||||
      return mockedDataSource;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void addingACustomerFailsWithExceptionAsFeedbackToClient() throws Exception {
 | 
			
		||||
      dao.add(new Customer(2, "Bernard", "Montgomery"));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Test
 | 
			
		||||
    public void deletingACustomerFailsWithExceptionAsFeedbackToTheClient() throws Exception {
 | 
			
		||||
      dao.delete(existingCustomer);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Test
 | 
			
		||||
    public void updatingACustomerFailsWithFeedbackToTheClient() throws Exception {
 | 
			
		||||
      final String newFirstname = "Bernard";
 | 
			
		||||
      final String newLastname = "Montgomery";
 | 
			
		||||
      
 | 
			
		||||
      dao.update(new Customer(existingCustomer.getId(), newFirstname, newLastname));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Test
 | 
			
		||||
    public void retrievingACustomerByIdFailsWithExceptionAsFeedbackToClient() throws Exception {
 | 
			
		||||
      dao.getById(existingCustomer.getId());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Test
 | 
			
		||||
    public void retrievingAllCustomersFailsWithExceptionAsFeedbackToClient() throws Exception {
 | 
			
		||||
      dao.getAll();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Delete customer schema for fresh setup per test.
 | 
			
		||||
   * @throws SQLException if any error occurs.
 | 
			
		||||
   */
 | 
			
		||||
  @After
 | 
			
		||||
  public void deleteSchema() throws SQLException {
 | 
			
		||||
    try (Connection connection = DriverManager.getConnection(DB_URL);
 | 
			
		||||
        Statement statement = connection.createStatement()) {
 | 
			
		||||
      statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void assertCustomerCountIs(int count) throws Exception {
 | 
			
		||||
    try (Stream<Customer> allCustomers = dao.getAll()) {
 | 
			
		||||
      assertTrue(allCustomers.count() == count);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * An arbitrary number which does not correspond to an active Customer id.
 | 
			
		||||
   * 
 | 
			
		||||
   * @return an int of a customer id which doesn't exist
 | 
			
		||||
   */
 | 
			
		||||
  private int getNonExistingCustomerId() {
 | 
			
		||||
    return 999;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										164
									
								
								dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,164 @@
 | 
			
		||||
/**
 | 
			
		||||
 * The MIT License
 | 
			
		||||
 * Copyright (c) 2014 Ilkka Seppälä
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.iluwatar.dao;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
import static org.junit.Assert.assertFalse;
 | 
			
		||||
import static org.junit.Assert.assertNull;
 | 
			
		||||
import static org.junit.Assert.assertTrue;
 | 
			
		||||
import static org.junit.Assume.assumeTrue;
 | 
			
		||||
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
 | 
			
		||||
import de.bechte.junit.runners.context.HierarchicalContextRunner;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests {@link InMemoryCustomerDao}.
 | 
			
		||||
 */
 | 
			
		||||
@RunWith(HierarchicalContextRunner.class)
 | 
			
		||||
public class InMemoryCustomerDaoTest {
 | 
			
		||||
 | 
			
		||||
  private InMemoryCustomerDao dao;
 | 
			
		||||
  private static final Customer CUSTOMER = new Customer(1, "Freddy", "Krueger");
 | 
			
		||||
 | 
			
		||||
  @Before
 | 
			
		||||
  public void setUp() {
 | 
			
		||||
    dao = new InMemoryCustomerDao();
 | 
			
		||||
    assertTrue(dao.add(CUSTOMER));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Represents the scenario when the DAO operations are being performed on a non existent 
 | 
			
		||||
   * customer.  
 | 
			
		||||
   */
 | 
			
		||||
  public class NonExistingCustomer {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void addingShouldResultInSuccess() throws Exception {
 | 
			
		||||
      try (Stream<Customer> allCustomers = dao.getAll()) {
 | 
			
		||||
        assumeTrue(allCustomers.count() == 1);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
 | 
			
		||||
      boolean result = dao.add(nonExistingCustomer);
 | 
			
		||||
      assertTrue(result);
 | 
			
		||||
 | 
			
		||||
      assertCustomerCountIs(2);
 | 
			
		||||
      assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
 | 
			
		||||
      final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
 | 
			
		||||
      boolean result = dao.delete(nonExistingCustomer);
 | 
			
		||||
 | 
			
		||||
      assertFalse(result);
 | 
			
		||||
      assertCustomerCountIs(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
 | 
			
		||||
      final int nonExistingId = getNonExistingCustomerId();
 | 
			
		||||
      final String newFirstname = "Douglas";
 | 
			
		||||
      final String newLastname = "MacArthur";
 | 
			
		||||
      final Customer customer = new Customer(nonExistingId, newFirstname, newLastname);
 | 
			
		||||
      boolean result = dao.update(customer);
 | 
			
		||||
 | 
			
		||||
      assertFalse(result);
 | 
			
		||||
      assertFalse(dao.getById(nonExistingId).isPresent());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void retrieveShouldReturnNoCustomer() throws Exception {
 | 
			
		||||
      assertFalse(dao.getById(getNonExistingCustomerId()).isPresent());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Represents the scenario when the DAO operations are being performed on an already existing
 | 
			
		||||
   * customer.
 | 
			
		||||
   */
 | 
			
		||||
  public class ExistingCustomer {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception {
 | 
			
		||||
      boolean result = dao.add(CUSTOMER);
 | 
			
		||||
 | 
			
		||||
      assertFalse(result);
 | 
			
		||||
      assertCustomerCountIs(1);
 | 
			
		||||
      assertEquals(CUSTOMER, dao.getById(CUSTOMER.getId()).get());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception {
 | 
			
		||||
      boolean result = dao.delete(CUSTOMER);
 | 
			
		||||
 | 
			
		||||
      assertTrue(result);
 | 
			
		||||
      assertCustomerCountIs(0);
 | 
			
		||||
      assertFalse(dao.getById(CUSTOMER.getId()).isPresent());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation() throws Exception {
 | 
			
		||||
      final String newFirstname = "Bernard";
 | 
			
		||||
      final String newLastname = "Montgomery";
 | 
			
		||||
      final Customer customer = new Customer(CUSTOMER.getId(), newFirstname, newLastname);
 | 
			
		||||
      boolean result = dao.update(customer);
 | 
			
		||||
 | 
			
		||||
      assertTrue(result);
 | 
			
		||||
 | 
			
		||||
      final Customer cust = dao.getById(CUSTOMER.getId()).get();
 | 
			
		||||
      assertEquals(newFirstname, cust.getFirstName());
 | 
			
		||||
      assertEquals(newLastname, cust.getLastName());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Test
 | 
			
		||||
    public void retriveShouldReturnTheCustomer() {
 | 
			
		||||
      Optional<Customer> optionalCustomer = dao.getById(CUSTOMER.getId());
 | 
			
		||||
      
 | 
			
		||||
      assertTrue(optionalCustomer.isPresent());
 | 
			
		||||
      assertEquals(CUSTOMER, optionalCustomer.get());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * An arbitrary number which does not correspond to an active Customer id.
 | 
			
		||||
   * 
 | 
			
		||||
   * @return an int of a customer id which doesn't exist
 | 
			
		||||
   */
 | 
			
		||||
  private int getNonExistingCustomerId() {
 | 
			
		||||
    return 999;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  private void assertCustomerCountIs(int count) throws Exception {
 | 
			
		||||
    try (Stream<Customer> allCustomers = dao.getAll()) {
 | 
			
		||||
      assertTrue(allCustomers.count() == count);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								pom.xml
									
									
									
									
									
								
							@@ -50,6 +50,7 @@
 | 
			
		||||
 		<guava.version>19.0</guava.version>
 | 
			
		||||
		<systemrules.version>1.15.1</systemrules.version>
 | 
			
		||||
		<mockito.version>1.10.19</mockito.version>
 | 
			
		||||
		<hierarchical-junit-runner-version>4.12.1</hierarchical-junit-runner-version>
 | 
			
		||||
	</properties>
 | 
			
		||||
	<modules>
 | 
			
		||||
		<module>abstract-factory</module>
 | 
			
		||||
@@ -196,6 +197,12 @@
 | 
			
		||||
				<version>${systemrules.version}</version>
 | 
			
		||||
				<scope>test</scope>
 | 
			
		||||
			</dependency>
 | 
			
		||||
			<dependency>
 | 
			
		||||
				<groupId>de.bechte.junit</groupId>
 | 
			
		||||
  				<artifactId>junit-hierarchicalcontextrunner</artifactId>
 | 
			
		||||
  				<version>${hierarchical-junit-runner-version}</version>
 | 
			
		||||
  				<scope>test</scope>
 | 
			
		||||
			</dependency>
 | 
			
		||||
		</dependencies>
 | 
			
		||||
	</dependencyManagement>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user