Archive for the 'databases' Category

17
Dec
09

Querying a Database using Spring JdbcTemplate

This page describes the process of querying data from a database using The Spring Framework’s JdbcTemplate and SimpleJdbcTemplate.

One of the first things that catches our eye when we start using the spring framework is the JdbcTemplate.

The following is the DDL for the table we will be using to run Queries. It holds movie Genre’s. Its a simple table with 2 columns.

CREATE TABLE IF NOT EXISTS `GENRE` (
  `GNR_I` int(11) NOT NULL AUTO_INCREMENT,
  `GNR_X` varchar(40) DEFAULT NULL,
  PRIMARY KEY (`GNR_I`)
)

JdbcTemplate

(legacy) This class is considered legacy. If you want to take advantages of the Java 5 features then use SimpleJdbcTemplate in the next section.

The following code queries the Genre table.

package test;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

@Component("genreDataManager")
public class GenreDataManagerImpl implements GenreDataManager {
	private JdbcTemplate jdbcTemplate;

	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	@Autowired
	@Required
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	public List<Genre> getAllGenre() {
		List genreList = this.jdbcTemplate.query(
			    "select gnr_i, gnr_x from GENRE",
			    new RowMapper() {
			        public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
			            Genre genre = new Genre();
			            genre.setId(rs.getInt(1));
			            genre.setName(rs.getString(2));
			            return genre;
			        }
			    });
		return genreList;
	}
}

SimpleJdbcTemplate

This class takes advantage of varargs and autoboxing, and exposing only the most commonly required operations in order to simplify JdbcTemplate usage. Use this class instead of the plain old JdbcTemplate.

The following is the same thing but using SimpleJdbcTemplate

package test;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.stereotype.Component;

@Component("genreDataManager")
public class GenreDataManagerImpl implements GenreDataManager {
	private SimpleJdbcTemplate jdbcTemplate;

	public SimpleJdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	@Autowired
	@Required
	public void setJdbcTemplate(SimpleJdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	public List<Genre> getAllGenre() {
		List<Genre> genreList = this.jdbcTemplate.<Genre>query(
			    "select gnr_i, gnr_x from GENRE",
			    new ParameterizedRowMapper<Genre>() {
			        public Genre mapRow(ResultSet rs, int rowNum) throws SQLException {
			            Genre genre = new Genre();
			            genre.setId(rs.getInt(1));
			            genre.setName(rs.getString(2));
			            return genre;
			        }
			    });
		return genreList;
	}
}

ApplicationContext.xml

The following file defines the jdbcTemplate and datasource. With these minimal settings you can successfully query a database.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<!-- The following is used for the @Autowired and @Required, @Resource etc... java.sql.DriverManager -->
	<context:annotation-config/>
	<context:component-scan base-package="test"/>
	<!-- This is a quick and dirty way to setup a datasource -->
	<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
		<property name="url" value="dburl"/>
		<property name="username" value="dbusername"/>
		<property name="password" value="password"/>
	</bean>

	<bean name="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
		<constructor-arg><ref bean="dataSource"/></constructor-arg>
	</bean>
</beans>
27
Oct
09

Ibatis 2.3 spring 2.5 Hello World

This page describes a very simple HelloWorld type application being created so that it can be used as a base for more complex projects.

We start out with adding this to an already created pom.xml file.

		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-sqlmap</artifactId>
			<version>2.3.4.726</version>
		</dependency>

If you have not done so already add the jdbc drivers for your database. In my case I am using mySQL.

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.9</version>
		</dependency>

regenerate the eclipse project:
mvn eclipse:clean eclipse:eclipse

REturn back to eclipse and refresh the project.

IBatis Main Configuration File

We first start with defining the main configuration file for the Ibatis framework. If you are working with a web application this is typically your WEB-INF folder. If you were using ibatis as a standalone framework you would have needed to put additional configuration entries in this file. However since we are using this with the state of-the-art dependency injection functionality provided by the spring framework.

MappersConfig.xml currently contains the locations of all the xml configuration files of all the individual sqlMap files.

MapperConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
        PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
        "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
    <sqlMap resource="com/vermatech/electronics/repository/ItemDataManager.xml"/>
</sqlMapConfig>

SQL Maps configuration files

Each SQL MAp resource specifies a set of sql statements that may be run against an entity. Inserts, updates, deletes etc are specified within XML syntax. In addition to SQL Statements you may specify additional attributes like how long you want the statements to cache. Aliases may be defined for class names. REsults map for returned results and parameter map for parameters.

Parameters Maps and Result Maps

Here is an example that uses parameters map and results maps explicitly

<typeAlias alias=”product” type=”com.ibatis.example.Product” />
<parameterMap id=”productParam” class=”product”>
         <parameter property=”id”/>
</parameterMap>
<resultMap id=”productResult” class=”product”>
         <result property=”id” column=”PRD_ID”/>
         <result property=”description” column=”PRD_DESCRIPTION”/>
</resultMap>
<select id=”getProduct” parameterMap=”productParam”
         resultMap=”productResult” cacheModel=”product-cache”>
    select * from PRODUCT where PRD_ID = ?
</select>

If you want to keep the xml configuration simple you can have Ibatis make educated guesses on how to map a Bean to Parameter and from Results back to beans. There is a slight performance consequence in that this approach requires accessing the ResultSetMetaData. This limitation can be overcome by using an explicit resultMap. Result maps are described in more detail later in this document. This uses the auto mapping feature of the framework which could be slower than if you specified the mappings yourself.

Here is an example that allows the sqlMap to make educated guesses about the mappings

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
  PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
  "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace=”Product”>
   <select id=”getProduct” parameterClass=” com.ibatis.example.Product”
                              resultClass=”com.ibatis.example.Product”>
         select
            PRD_ID as id,
            PRD_DESCRIPTION as description
         from PRODUCT
         where PRD_ID = #id#
   </select>
</sqlMap>

Since the developer is specifying SQL witin XML you need the ability to escape characters that would appear in xml. An example is the < and > signs.

<select id="getPersonsByAge" parameterClass=”int” resultClass="examples.domain.Person">
         SELECT *
         FROM PERSON
         WHERE AGE <![CDATA[ > ]]> #value#
</select>

SQL Fragments

In order to reduce SQL Code duplication you can use things like Fragments but keep in mind that it does increase the amount of testing effort if something in the common fragment changes.

Here is an example:

<sql id="selectItem_fragment">
         FROM items
         WHERE parentid = 6
</sql>
<select id="selectItemCount" resultClass="int">
         SELECT COUNT(*) AS total
         <include refid="selectItem_fragment"/>
</select>
<select id="selectItems" resultClass="Item">
         SELECT id, name
         <include refid="selectItem_fragment"/>
</select>

Auto generated keys

Supported by using the following XML code

<!—Oracle SEQUENCE Example -->
<insert id="insertProduct-ORACLE" parameterClass="com.domain.Product">
    <selectKey resultClass="int" >
         SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL
    </selectKey>
    insert into PRODUCT (PRD_ID,PRD_DESCRIPTION)
    values (#id#,#description#)
</insert>
<!— Microsoft SQL Server IDENTITY Column Example -->
<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product">
    insert into PRODUCT (PRD_DESCRIPTION)
    values (#description#)
    <selectKey resultClass="int" >
         SELECT @@IDENTITY AS ID
    </selectKey>
</insert>

Calling Stored Procedures

<parameterMap id="swapParameters" class="map" >
  <parameter property="email1" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
  <parameter property="email2" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
</parameterMap>
<procedure id="swapEmailAddresses" parameterMap="swapParameters" >
  {call swap_email_address (?, ?)}
</procedure>

The next steps are to start coding your CRUD operations on your objects. I talk about this in more detail at the following page




Follow

Get every new post delivered to your Inbox.

Join 49 other followers