Feb 26

5 Minute Guide to Spring and Simple[r!] JDBC

Tag: java, jdbc, springpmularien @ 1:05 am

I have noticed a trend recently among some folks in the Java world, where it is simply taken for granted that an ORM provider (usually Hibernate) will be automatically inserted in the technology stack of any new project. Quite often, this happens with little to no technical justification or analysis. If you’re reading this and nodding your head, this should be frightening to you. The reason is that if the use of an ORM isn’t required, it can cause projects (especially small ones) to have unneeded complexity. Additionally, abstraction without understanding what’s underneath can set a dangerous level of ignorance on the part of developers, who will simply collapse when the abstraction breaks and critical thinking through the abstraction is required to solve a problem.

In that spirit, I recently worked on a personal project to learn how one can write dead-simple plain old JDBC applications using only Spring Framework 2.5 without an ORM layer. Spring 2.5 has many features that provide some of the convenience of ORM libraries (simple mapping from ResultSets to Objects), some convenience above and beyond ORM libraries (mapping from ResultSets to primitives!*), and removes some of the complexity (caching, cascading, etc.). For applications with fewer tables than you have fingers on your hand, this can greatly ease development.

I’ll assume you already know how to work with Spring, and at least know (or can dredge up) the basics of JDBC. We’ll work through a simple example, mapping the ubiquitous “Person” table to a Person object, and back again through an insert operation. Hopefully this will open your mind to non-ORM solutions. I promise that in 5 minutes (or less!) you will be amazed at the things you can do with simple JDBC ;)

Table Definition

Although the particular database we’re using isn’t really important, if you’re following along, in this particular example I’ve used SQL Server. The table definition looks like this (a bit verbose, since I used the SQL export feature of SQL server):

CREATE TABLE [dbo].[Person](
	[ID] [uniqueidentifier] ROWGUIDCOL  NOT NULL CONSTRAINT [DF_Person_ID]  DEFAULT (newid()),
	[FirstName] [nchar](30),
	[MiddleName] [nchar](20),
	[LastName] [nchar](50),
	[Suffix] [nchar](10),
	[Address1] [nchar](100),
	[Address2] [nchar](100),
	[City] [nchar](35),
	[State] [nchar](2),
	[ZipCode] [nchar](9),
 CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
 (
	[ID] ASC
 )
);

Basically, this is a table with a few columns containing attributes common to people.

Data Access

First, we will write a simple DAO. This DAO will have a method to find people residing in a specific state. The method will look something like the following:

	public List<Person> findPeopleByState(String state) {
		// <fill in>
	}

Seems pretty simple. OK, let’s fill in the method body.

	public List<Person> findPeopleByState(String state) {
		return jdbcTemplate.query("select p.* from Person p where p.state = ?", new PersonRowMapper(), state);
	}

Let’s look at what we have here. We have a single line which will do the following:

  • Execute a SQL JDBC query
  • Accept a parameter
  • Map the JDBC ResultSet to a List of Person objects

Did you know you could do this with Spring and JDBC? I didn’t, until I ran across this gem. Let’s work from the bottom up. We write an inner class PersonRowMapper, which implements the ParameterizedRowMapper<T> interface from the org.springframework.jdbc.core.simple package.

Basically, classes implementing this interface must, given a ResultSet, return an object of the declared generic type. Here’s our PersonRowMapper implementation (Note that @Override is supported on interface implementation methods only on Java 6, so remove that annotation if you’re on Java 5):

	class PersonRowMapper implements ParameterizedRowMapper<Person> {
 
		@Override
		public Person mapRow(ResultSet resultSet, int rowNum) throws SQLException {
			Person p = new Person();
			p.setFirstName(resultSet.getString("FirstName"));
			p.setLastName(resultSet.getString("LastName"));
			// etc.
			p.setZip(resultSet.getString("ZipCode"));
			return p;
		}		
	}

Dead simple ORM-like behavior. If you’re like me, you’ve probably written this exact same thing yourself at least 3 times before using JDBC. The magic lies in the SimpleJdbcTemplate class which was introduced in Spring 2.0. (Interested readers will note that due to its reliance on several language features, SimpleJdbcTemplate and its siblings require Java 5 or higher at runtime.)

Constructing our DAO looks like the following:

@Repository
public class JdbcPersonSearchDao implements PersonSearchDao {
	private SimpleJdbcTemplate jdbcTemplate;
 
	@Autowired
	public JdbcPersonSearchDao(DataSource dataSource) {
		jdbcTemplate = new SimpleJdbcTemplate(dataSource);
	}
 
	// class body
}

Note that from the outside, the DI weaver doesn’t notice anything different from any other JDBC-using DAO.

To return to our JDBC query, let’s quickly explain the rest of the one liner:

The query method is one of the many convenience methods built into SimpleJdbcTemplate. Others allow you to easily return a list of primitives, a Map of column name, value pairs, etc. Adding query parameters is supported in many flavors, my favorite being the varargs option that we’re using here.

The beauty of the ParameterizedRowMapper that we write is that it can easily be reused in other queries, or subclassed for queries that return supersets of data (imagine a complex table, which in some cases returns a set of columns C1 … Cn, and in other cases C1 … Cn+m).

Ease of Extension

I ran pretty quickly into a simple case that wasn’t covered by the provided functionality. I wanted to return a List of the distinct set of states in the Person table. With a (literally) one minute inner class, I was in business:

	public List<String> getAvailableStates() {
		return jdbcTemplate.query("select distinct State from Person order by State", new ParameterizedRowMapper<String>() {
			@Override
			public String mapRow(ResultSet rs, int rowNum) throws SQLException {
				return rs.getString("State");
			}
		});
	}

Hopefully you’re excited by this, and it gives you a chance to try out some raw JDBC to simplify your Spring-based applications. Please write in the comments if you have any additional questions/concerns/feedback. As and when I get time, I’ll cover JDBC inserts using the SimpleJdbcTemplate, which are, as expected, also quite, erm, simple ;)

Related Reading

I tried very hard to come up with reference material for this entry. Unfortunately I was only able to find Ben Hale’s entry on the SpringSource Team Blog from way back in 2006 when this stuff was introduced.

Of course, the friendly Spring Data Access forum is a good place to ask questions as well. Enjoy!

13 Responses to “5 Minute Guide to Spring and Simple[r!] JDBC”

  1. lumpynose says:

    Between Hibernate and raw JDBC is iBatis.

  2. anjan bacchu says:

    hi there,

    I recently got the experience of converting most of the use cases of a spring-hibernate app to spring-jdbc app.

    I used SimpleJdbcTemplate (from spring) to make my life easier. Go through the JDBC tutorial from the spring website : it is pretty good.

    BR,
    ~A

  3. djo.mos says:

    Hi,
    Nice article: I’m personally using Spring JDBC in a medium-sized project at work, and while quite verbose compared to ORMs, the flexibility is just unbeatable ;-)

    Anyway, I wanted to point it out that the RowMapper would be better declared as an inner static class inside the DAO, thus alleviating us from some unnecessary instantiations.

    Cheers.

  4. pmularien says:

    @djo.mos:
    Actually, I was using RowMappers as inner static classes when I was working with these - but for simplicity purposes, I illustrated them in this article as anonymous inner classes :) I agree that if your RowMapper is anything more than a one-liner, you should pull it out into its own class.

    @anjan.bacchu:
    By “JDBC tutorial”, are you referring to the JDBC portion of the Spring MVC Step-by-Step tutorial?

  5. Andy Y says:

    There is another way to write your last example (with the a cast):

    public List<String> getAvailableStates() {
      return (List<String>)jdbcTemplate. getJdbcOperations().queryForList("select distinct State from Person order by State", String.class);
    }

    Just a pity about the casting :(

  6. Kasper Graversen says:

    Hi all.

    Often people complain about generating dynamic queries. I’ve just started a project called SQLOrm. One day it will be a full fledged ORM, but for now It helps you generate dynamic SQL queries.

    It generates strings so you can use it with Spring etc. Its free and open source.
    See more at

    http://sqlorm.sourceforge.net/dynamic_query_builder_doc.html

  7. Blog bookmarks 02/27/2008 « My Diigo bookmarks says:

    [...] It’s Only Software » 5 Minute Guide to Spring and Simple[r!] JDBC [...]

  8. It’s Only Software » Auto-Expanding Collections as JDBC Parameters with Spring SimpleJdbcTemplate says:

    [...] under the heading Passing in lists of values for IN clause. You can also read my own article on a 5 Minute Guide to Spring and Simpler JDBC for an introduction on the new Spring 2.5 JDBC features. addthis_url = [...]

  9. Gene says:

    You cannot use @Override with iterface methods.

  10. pmularien says:

    @Override is supported on interfaces in Java 6 and not on any prior version. Good catch, I will make a note in the post.

  11. Bryan Shannon says:

    You’re absolutely right here… Hibernate can kill smaller, or even midsize projects. And if you have DBA that likes to do DBA-type-work, then you might be forced into a life of pain trying to get Hibernate to live well with him/her.

    I’m an iBatis fan, and have been for years. But the straight JDBC stuff from Spring should definitely be looked into before digging into Hibernate for the first time. I wish I would have done that for myself before making a fool of myself sitting across from Tom Risberg *cough, cough* at lunch during the Spring Experience 2007, casually telling him how much ‘I love iBatis….’ :-) Hi Tom…

    Seriously, though… For most needs, getting rid of the boilerplate code you need for your data access is the most important… (ibatis and spring-loaded jdbc fit the bill here)… Dealing with more complex ORM’s might leave you feeling bloated.

  12. It’s Only Software » Quick Tip: JDBC ParameterizedSingleColumnRowMapper in Spring 2.5.2+ says:

    [...] for simple JDBC queries performed with the generics-aware SimpleJdbcTemplate (read my earlier 5 Minute Guide to… if you don’t know what this is). Change this: new [...]

  13. Guiluan Luo says:

    FireStorm/DAO is a tool to automatically generate Spring JDBC DAO tier objects. It is very good tool and it is free.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">