Browse DevX
Sign up for e-mail newsletters from DevX


Spring: Creating Objects So You Don't Have To : Page 4

As a dependency injection framework (not to mention one of the more popular open source Java projects today), Spring links objects together using XML definitions. Find out about Spring and the ways you can invert control in your object programming.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

JDBC Support
As a consultant, I have worked with many different development teams, but I still can't get over the fact that so many developers rewrite something similar to Listing 2 every single time they want to make a connection to the database.

If this block of code is spread throughout your code and you have seen and written it so many times that it is easy to regurgitate from memory, you probably aren't writing reusable JDBC code.

The majority of this code deals with the creation and release of database resources and query execution. The only part of the code that is unique for each database interaction is the query string and the logic in the doSomethingWithResultSet() method. The resource-handling and query-executing code can easily be separated from your data-accessing code and encapsulated within a "template." This template can then be provided with a query to execute on your behalf. A callback mechanism can be put in place for the template to call back the client code so that the client code can handle the ResultSet before the template cleans up the resources.

This type of separation of responsibilities makes for better OO design. Fortunately, thanks to Spring, you don't have to implement this database-access template yourself. You can use Spring's JdbcTemplate class to interact with a database through JDBC. Above and beyond the basic functionality we just discussed, JdbcTemplate provides many convenience methods for doing things such as converting database data into primitives or objects, executing prepared and callable statements, and providing custom database error handling.

Let's look at an example of a DataReader that would read data from a database using JDBC:

class DatabaseDataReader implements DataReader… private DataSource dataSource; public DatabaseDataReader(DataSource dataSource) { this.dataSource = dataSource; } public Data readData() { JdbcTemplate template = new JdbcTemplate(dataSource); int value1 = template .queryForInt("select value1 from data where primary_key = 1"); int value2 = template .queryForInt("select value2 from data where primary_key = 1"); return new Data(value1, value2); } }

The readData() method creates a JdbcTemplate, taking a java.sql.DataSource object as a parameter. The read data method makes two queries to the database to get the values that it needs to create a Data object. As you can see, each query makes use of the template's queryForInt() method. This method returns the value of the query as a primitive int. After profiling your application, if we were to find out that making two database calls in this method was affecting your overall application performance, you could optimize your readData() method as follows:

class DatabaseDataReader implements DataReader… public Data readData() { JdbcTemplate template = new JdbcTemplate(dataSource); List values = template .queryForList("select value1, value2 from data where primary_key = 1"); Map valueMap = (Map) values.get(0); int value1 = ((Integer) valueMap.get("value1")).intValue(); int value2 = ((Integer) valueMap.get("value2")).intValue(); return new Data(value1, value2); }

Now you are using the queryForList() method, which returns a list of maps. Each entry in the list represents a row from the resulting query, and each entry in the map represents a column-name/cell-value pair.

If you had more complicated mapping to do, you could utilize Spring's RowCallbackHandler:

class DatabaseDataReader implements DataReader, RowCallbackHandler… public Data readData() { JdbcTemplate template = new JdbcTemplate(dataSource); template.query("select value1, value2 from data where primary_key = 1", this); return new Data(value1, value2); } public void processRow(ResultSet resultSet) throws SQLException { value1 = resultSet.getInt("value1"); value2 = resultSet.getInt("value2"); }

As you can see, the DatabaseDataReader class now implements RowCallbackHandler, which defines a processRow() method. When you call the query() method on JdbcTemplate you pass in a query string as well as a reference to a RowCallbackHandler. Because you are the callback handler, you pass in a reference to "this." As Spring is going through its query workflow, it will make a call back to the processRow() method on your DatabaseDataReader object after it has created the database resources and executed the query. You will use the ResultSet object however you need to in the processRow() method, then when the processRow() method finishes running, the query method continues by releasing all necessary database resources.

As you may have noticed, you are passing a datasource in as an argument to the DataReader constructor. What a perfect place to use dependency injection! Here is what your bean definition would look like for a DataSource using mySQL and a database named "spring":

<bean name="dataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" destroy-method="close"> <property name="url"> <value>jdbc:mysql://localhost/spring</value> </property> <property name="user"> <value></value> </property> <property name="password"> <value></value> </property> </bean>

As you have learned, Spring can be used as an underlying factory mechanism in your code. Your application code can access object through Spring, and the parameters provided to those objects can be changed without recompiling your application. You learned about how Spring provides other functionality, such as the JdbcTemplate, and how such functionality ties in to its underlying dependency injection framework. In the follow-up to this article, I will show you how to build a simple Web application using Spring's MVC framework.

Javid Jamae consults for Valtech, a global consulting group specializing in delivering advanced technology solutions. Valtech endeavors to help its customers through its global delivery model to create and/or maintain an affordable competitive advantage.
Thanks for your registration, follow us on our social networks to keep up-to-date