Look at the
PhoneBookDerbyDao
class. It has 398 lines to support create, read, update, and delete (CRUD) operations. Every method performs almost similar tasks. The following tasks are invoked from the CRUD methods:
The Spring framework provides APIs to reduce JDBC code duplication. Spring JDBC hides the low-level details and allows us to concentrate on business logic. We'll implement PhoneBookDao
using Spring JDBC.
Download the latest version of JDBC JAR and its dependencies from http://maven.springframework.org/release/org/springframework/spring/.
Follow the ensuing steps to implement Spring JDBC and simplify the code:
DatabaseAccess
project, and edit .classpath
to add the following Spring dependencies shown in the screenshot:PhoneBookDerbySpringDao
class that implements the PhoneBookDao
interface. The following is the Spring implementation of the create
method:public class PhoneBookDerbySpringDao implements PhoneBookDao { private final JdbcTemplate jdbcTemplate; public PhoneBookDerbySpringDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @Override public boolean create(PhoneEntry entry) { int rowCount = jdbcTemplate.update("insert into PhoneBook values (?,?,?)", new Object[]{entry.getPhoneNumber(), entry.getFirstName(), entry.getLastName() }); return rowCount == 1; } }
JdbcTemplate
simplifies the use of JDBC; it handles the resources and helps to avoid common errors such as not closing the connection. It creates and populates the statement
object, iterates through the ResultSet
object, which leaves the application code to provide SQL, and extracts results. PhoneBookDerbySpringDao
contains a JdbcTemplate
instance and delegates the database tasks to the jdbcTemplate
.
JdbcTemplate
has an update method for insert and update operations. It takes a SQL query and parameters. The new Spring version of the create()
method invokes the update()
method on jdbcTemplate
and passes PhoneEntry
details. Now the create
method looks simple, just two lines of code. The Spring framework handles the resource life cycle.
PhoneBookDerbySpringDaoTest
for unit testing. We'll create a jdbcTemplate
mock and pass it to dao. The following is the JUnit implementation:@RunWith(MockitoJUnitRunner.class) public class PhoneBookDerbySpringDaoTest { @Mock JdbcTemplate mockJdbcTemplate; PhoneBookDerbySpringDao springDao; @Before public void init() { springDao = new PhoneBookDerbySpringDao(mockJdbcTemplate); } @Test public void creates_PhoneEntry() throws Exception { //create PhoneEntry String charlsPhoneNumber = "1234567"; String charlsFirstName = "Charles"; String charlsLastName = "Doe"; PhoneEntry charles = new PhoneEntry(); charles.setFirstName(charlsFirstName); charles.setLastName(charlsLastName); charles.setPhoneNumber(charlsPhoneNumber); //Stub jdbcTemplate's update to return 1 when(mockJdbcTemplate.update(anyString(), anyObject(), anyObject(), anyObject())).thenReturn(1); //Execute assertTrue(springDao.create(charles)); //Create argument capture ArgumentCaptor<Object> varArgs = ArgumentCaptor.forClass(Object.class); ArgumentCaptor<String> strArg = ArgumentCaptor.forClass(String.class); //Verify update method was called and capture args verify(mockJdbcTemplate).update(strArg.capture(),varArgs.capture(),varArgs.capture(), varArgs.capture()); //Verify 1st dynamic argument was the phone number assertEquals(charlsPhoneNumber, varArgs.getAllValues().get(0)); //Verify the name arguments assertEquals(charlsFirstName, varArgs.getAllValues().get(1)); assertEquals(charlsLastName, varArgs.getAllValues().get(2)); } }
Look at the new Spring dao; it is only 54 lines long. The class looks neat, simple, and readable. It doesn't handle resources, it rather concentrates on data access.