Spring的一個(gè)目標(biāo)就是讓你遵循對(duì)接口編程的面向?qū)ο笤瓌t。DAO的存在提供了讀寫數(shù)據(jù)庫中數(shù)據(jù)的一種方
法。只要把這個(gè)功能通過接口暴露,應(yīng)用的其他部分就可以通過這些接口訪問數(shù)據(jù)庫了。
在Spring的DAO框架里,Connection對(duì)象是通過DataSource獲得的。
從JNDI得到DataSource,代碼:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<!-- Spring應(yīng)用經(jīng)常運(yùn)行在J2EE應(yīng)用服務(wù)器上,或者是諸如Tomcat的Web服務(wù)器上。這些服務(wù)器都能提供的一件事:通過
JNDI獲得DataSource.現(xiàn)在我們已經(jīng)和服務(wù)器上的DataSource以及它的連接池功能連接上了。
-->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/myDatasource</value>
</property>
</bean>
<!-- 加入Spring容器運(yùn)行在一個(gè)不提供DataSource的環(huán)境中,但我們還希望擁有連接池的好處,我們要實(shí)現(xiàn)一個(gè)DataSource
的連接池Bean,我們有了一個(gè)帶連接池的DataSource,它不依賴于任何應(yīng)用服務(wù)器,代碼如下: -->
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>${db.driver}</value>
</property>
<property name="url">
<value>${db.url}</value>
</property>
<property name="username">
<value>${db.username}</value>
</property>
<property name="password">
<value>${db.password}</value>
</property>
</bean>
</beans>
一個(gè)模版方法定義一個(gè)流程的骨架。在我們的例子中,這個(gè)流程就是把行李從出發(fā)地運(yùn)送到目的地。流程本身是固定的,不會(huì)改變。處理行李的事件順序每一次都是一樣的:檢查行李、放到飛機(jī)上等等。當(dāng)飛機(jī)到達(dá)目的地時(shí),行李都被一件件的卸下來,放到傳送帶上,再運(yùn)到行李提取處。流程是固定的,但是流程中的具體實(shí)現(xiàn)有些是可變的。一個(gè)模版方法將這部分可變流程的具體實(shí)現(xiàn)委托給一個(gè)接口,這個(gè)接口的不同實(shí)現(xiàn)定義了這部分流程的具體實(shí)現(xiàn)。
Spring把這個(gè)模式應(yīng)用到數(shù)據(jù)訪問上。不管我們采用什么技術(shù),某些數(shù)據(jù)訪問步驟是必須的。例如:我們總是需要和數(shù)據(jù)庫建立連接,在操作完后釋放資源。這就是數(shù)據(jù)訪問流程中的固定步驟。但我們寫的每個(gè)數(shù)據(jù)訪問的實(shí)現(xiàn)都有略微不同,我們用不同的方式查詢不同的對(duì)象、更新數(shù)據(jù)。這些就是數(shù)據(jù)訪問流程中的可變步驟。
Spring把數(shù)據(jù)訪問流程中的固定部分和可變部分分開,分別映射成2個(gè)截然不同的類:模版和回調(diào)。模版管理流程的固定部分,而在回調(diào)處填寫你的實(shí)現(xiàn)細(xì)節(jié)。
在模版和回調(diào)的設(shè)計(jì)之上,每個(gè)框架都提供一個(gè)支撐類,以便讓你自己的數(shù)據(jù)訪問類來繼承它們。這些支撐類早已擁有一個(gè)指向模版類的屬性,所以不需要為每個(gè)DAO類創(chuàng)建這個(gè)屬性。另外,每個(gè)支撐類都允許你直接得到用于跟數(shù)據(jù)庫打交道的類。
模版代碼使用如下:
package com.testproject.spring.datasource;

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

import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;

/**//*
* 為了讓JdbcTemplate工作,它所需要的,只是一個(gè)DataSource實(shí)例。
*/

public class StudentDaoJdbc implements StudentDao
{
private JdbcTemplate jdbcTemplate;

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

/**//*
* 先從SQL語句創(chuàng)建一個(gè)PreparedStatement,然后綁定參數(shù)。在幕后,JdbcTemplate
* 類創(chuàng)建了PreparedStatementCreator和PreparedStatementSetter.這些我們都
* 不用關(guān)心,我們只管提供SQL語句和參數(shù)。還可以提供類型支持。
*/

public int insertPerson(Person person)
{
String sql = "insert into person(id,firstName,lastName) values(?,?,?)";

Object[] params = new Object[]
{person.getId(),person.getFirstName(),person.getLastName()};
return jdbcTemplate.update(sql,params);
}

public int insertPerson2(Person person)
{
String sql = "insert into person(id,firstName,lastName) values(?,?,?)";

Object[] params = new Object[]
{person.getId(),person.getFirstName(),person.getLastName()};

int[] types = new int[]
{Types.INTEGER,Types.VARBINARY,Types.VARBINARY};
return jdbcTemplate.update(sql, params, types);
}

/**//*
* 批量更新,我們講使用BatchPreparedStatementSetter,這個(gè)接口的2個(gè)方法
* 1、getBatchSize()告訴JdbcTemplate類有多少個(gè)語句要?jiǎng)?chuàng)建,同時(shí)也決定了要調(diào)用多少次setValues()
* 2、setValues負(fù)責(zé)創(chuàng)建參數(shù)
* 所以你的JDBC驅(qū)動(dòng)支持批量操作,這些更新講被批量執(zhí)行,是的數(shù)據(jù)訪問更高效。
*/

public int[] updatePersons(final List persons)
{
String sql = "insert into person(id,firstName,lastName) values(?,?,?)";
BatchPreparedStatementSetter setter = null;

setter = new BatchPreparedStatementSetter()
{

public int getBatchSize()
{
return persons.size();
}

public void setValues(PreparedStatement ps,int index)throws SQLException
{
Person person = (Person)persons.get(index);
ps.setInt(0,person.getId().intValue());
ps.setString(1,person.getFirstName());
ps.setString(2,person.getLastName());
}
};
return jdbcTemplate.batchUpdate(sql, setter);
}

/**//*
* 當(dāng)查詢數(shù)據(jù)庫時(shí),我們需要通過ResultSet取得結(jié)果,Spring認(rèn)識(shí)到這一步是任何查詢都需要的,所以它幫助
* 我們處理了這些。取而代之,我們只需要簡單的告訴Spring要怎么處理ResultSet中的每一行記錄。我們通過
* 實(shí)現(xiàn)RowCallbackHandler接口中僅有的一個(gè)方法來完成上述功能。
* void processRow(java.sql.ResultSet rs)該方法將為ResultSet中的每條記錄調(diào)用一次
* 這個(gè)方法只支持單對(duì)象的查詢
*/

public Person getPerson(final Integer id)
{
String sql = "select id,first_Name,last_Name from person where id=?";
final Person person = new Person();//創(chuàng)建查詢結(jié)果對(duì)象

final Object[] params = new Object[]
{id};//創(chuàng)建查詢參數(shù)

jdbcTemplate.query(sql,params,new RowCallbackHandler()
{//處理查詢結(jié)果

public void processRow(ResultSet rs)throws SQLException
{
person.setId(new Integer(rs.getInt("id")));
person.setFirstName(rs.getString("first_name"));
person.setLastName(rs.getString("last_name"));
}
});
return person;//返回查詢結(jié)果對(duì)象
}

/**//*
* 查詢所有記錄
* RowMapper接口對(duì)從一個(gè)查詢結(jié)果中提取多個(gè)對(duì)象非常游泳。
*/

public List getAllPersons()
{
String sql = "select id,first_name,last_name from person";
return jdbcTemplate.query(sql,new PersonRowMapper());
}

/**//*
* 查找基本類型
*/

public int getNumberOfPerson()
{
return jdbcTemplate.queryForInt("select count(*) from person");
}

public String getLastNameForId(Integer id)
{
String sql = "select last_name from person where id=?";

return (String)jdbcTemplate.queryForObject(sql,new Object[]
{id},String.class);
}
}

package com.testproject.spring.datasource;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;


public class PersonRowMapper implements RowMapper
{


public Object mapRow(ResultSet rs, int index) throws SQLException
{
Person person = new Person();
person.setId(new Integer(rs.getInt("id")));
person.setFirstName(rs.getString("first_name"));
person.setLastName(rs.getString("last_name"));
return person;
}

}

posted on 2009-11-12 19:46
王永慶 閱讀(187)
評(píng)論(0) 編輯 收藏 所屬分類:
SPRING