在持久層的封裝與整合上,Spring作了許多的努力,這邊以一個簡單的實際例子來小小體會一下使用Spring所提供的持久層所帶來的優點之一(只是其中之一的優點,之後還會看到更多的實例,我一向喜歡從實例中體會框架的功能)。
首先請您先複習一下在Spring中如何進行DataSource的設定:
這邊我們設計一個簡單的UserDAO物件,我們直接使用JDBC,首先來看看Spring提供什麼樣的物件來簡化JDBC程式的撰寫:
代碼:
package onlyfun.caterpillar;
import javax.sql.DataSource;
import java.sql.*;
import org.springframework.jdbc.core.JdbcTemplate;
public class UserDAO {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void insertUser(User user) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update("INSERT INTO USER VALUES('"+ user.getId() + "', '"
+ user.getName() + "', '"
+ user.getSex() + "', '"
+ user.getAge() + "')");
}
public User queryUser(String id) {
....
}
...
}
這個DAO物件實現了手動的O/R Mapping,如您所見的,真正的儲存動作只要兩行程式,如果是使用傳統的JDBC程式撰寫,您的insertUser()可能像是這樣撰寫:
代碼:
package onlyfun.caterpillar;
import javax.sql.DataSource;
import java.sql.*;
import org.springframework.jdbc.core.JdbcTemplate;
public class UserDAO {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void insertUser(User user) {
Connection conn = null;
Statement stmt = null;
try {
conn = dataSource.getConnection();
stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO USER VALUES('"+ user.getId() + "', '"
+ user.getName() + "', '"
+ user.getSex() + "', '"
+ user.getAge() + "')");
}
catch(SQLException e) {
e.printStackTrace();
}
finally {
if(stmt != null) {
try {
stmt.close();
}
catch(SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
}
catch(SQLException e) {
e.printStackTrace();
}
}
}
}
public User queryUser(String id) {
....
}
....
}
您必須自行取得Connection與Statement物件、執行SQL、捕捉例外、關閉相關資源,當您使用Spring的JdbcTemplate時,卻只要兩行,Spring的JdbcTemplate封裝了傳統的JDBC程式執行流程,並為您作了例外處理與資源管理等動作,您所需要的只是一個給它一個DataSource,而這只要在bean定義檔中完成依賴注入:
代碼:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "- "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql: </property>
<property name="username">
<value>caterpillar</value>
</property>
<property name="password">
<value>123456</value>
</property>
</bean>
<bean id="userDAO" class="onlyfun.caterpillar.UserDAO">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
</beans>
Spring的JdbcTemplate一如其名稱所示的,主要是藉由Template Method模式來實現封裝,視您的需求而定,JdbcTemplate也可以在bean定義檔中生成,當作一個bean來源注入DAO中,例如我們的UserDAO可以修改如下:
代碼:
package onlyfun.caterpillar;
import javax.sql.DataSource;
import java.sql.*;
import org.springframework.jdbc.core.JdbcTemplate;
public class UserDAO {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void insertUser(User user) {
jdbcTemplate.update("INSERT INTO USER VALUES('"+ user.getId() + "', '"
+ user.getName() + "', '"
+ user.getSex() + "', '"
+ user.getAge() + "')");
}
public User queryUser(String id) {
....
}
....
}
而bean定義檔修改如下即可完成依賴注入:
代碼:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "- "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql: </property>
<property name="username">
<value>caterpillar</value>
</property>
<property name="password">
<value>123456</value>
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<bean id="userDAO" class="onlyfun.caterpillar.UserDAO">
<property name="jdbcTemplate">
<ref bean="jdbcTemplate"/>
</property>
</bean>
</beans>
更進一步的,我們還可以利用Spring IoC容器的功能,將SQL語句以依賴注入的方式設定給DAO,而不用像上例中直接寫死在DAO類別中。
Spring的Jdbc封裝等功能基本上可以獨立於Spring來使用,如您所看到的,JdbcTemplate所需要的就是一個DataSource物件,在不使用Spring IoC容器下,您可以單獨使用spring-dao.jar中的東西。
除了JdbcTemplate之外,Spring還提供了其它的Template類別,像是對Hibernate、JDO、ibatis等的Template實現,另外,在事務處理方面,Spring提供了編程式與宣告式的事務管理功能,大大的簡化了持久層程式的複雜度,並提供了更好的維護性,在之後的主題中將會一一介紹Spring在這些議題上所提供的功能。