Spring的一個目標就是讓你遵循對接口編程的面向對象原則。DAO的存在提供了讀寫數據庫中數據的一種方
法。只要把這個功能通過接口暴露,應用的其他部分就可以通過這些接口訪問數據庫了。
在Spring的DAO框架里,Connection對象是通過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應用經常運行在J2EE應用服務器上,或者是諸如Tomcat的Web服務器上。這些服務器都能提供的一件事:通過
JNDI獲得DataSource.現在我們已經和服務器上的DataSource以及它的連接池功能連接上了。
-->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/myDatasource</value>
</property>
</bean>
<!-- 加入Spring容器運行在一個不提供DataSource的環境中,但我們還希望擁有連接池的好處,我們要實現一個DataSource
的連接池Bean,我們有了一個帶連接池的DataSource,它不依賴于任何應用服務器,代碼如下: -->
<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>
一個模版方法定義一個流程的骨架。在我們的例子中,這個流程就是把行李從出發地運送到目的地。流程本身是固定的,不會改變。處理行李的事件順序每一次都是一樣的:檢查行李、放到飛機上等等。當飛機到達目的地時,行李都被一件件的卸下來,放到傳送帶上,再運到行李提取處。流程是固定的,但是流程中的具體實現有些是可變的。一個模版方法將這部分可變流程的具體實現委托給一個接口,這個接口的不同實現定義了這部分流程的具體實現。
Spring把這個模式應用到數據訪問上。不管我們采用什么技術,某些數據訪問步驟是必須的。例如:我們總是需要和數據庫建立連接,在操作完后釋放資源。這就是數據訪問流程中的固定步驟。但我們寫的每個數據訪問的實現都有略微不同,我們用不同的方式查詢不同的對象、更新數據。這些就是數據訪問流程中的可變步驟。
Spring把數據訪問流程中的固定部分和可變部分分開,分別映射成2個截然不同的類:模版和回調。模版管理流程的固定部分,而在回調處填寫你的實現細節。
在模版和回調的設計之上,每個框架都提供一個支撐類,以便讓你自己的數據訪問類來繼承它們。這些支撐類早已擁有一個指向模版類的屬性,所以不需要為每個DAO類創建這個屬性。另外,每個支撐類都允許你直接得到用于跟數據庫打交道的類。
模版代碼使用如下:
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工作,它所需要的,只是一個DataSource實例。
*/

public class StudentDaoJdbc implements StudentDao
{
private JdbcTemplate jdbcTemplate;

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

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

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,這個接口的2個方法
* 1、getBatchSize()告訴JdbcTemplate類有多少個語句要創建,同時也決定了要調用多少次setValues()
* 2、setValues負責創建參數
* 所以你的JDBC驅動支持批量操作,這些更新講被批量執行,是的數據訪問更高效。
*/

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);
}

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

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

final Object[] params = new Object[]
{id};//創建查詢參數

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

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;//返回查詢結果對象
}

/**//*
* 查詢所有記錄
* RowMapper接口對從一個查詢結果中提取多個對象非常游泳。
*/

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
王永慶 閱讀(185)
評論(0) 編輯 收藏 所屬分類:
SPRING