對JDBC的支持之集成Spring JDBC及最佳實踐
來自: http://www.importnew.com/18104.html
7.5 集成Spring JDBC及最佳實踐
大多數情況下Spring JDBC都是與IOC容器一起使用。通過配置方式使用Spring JDBC。
而且大部分時間都是使用JdbcTemplate類(或SimpleJdbcTemplate和NamedParameterJdbcTemplate)進行開發,即可能80%時間使用JdbcTemplate類,而只有20%時間使用其他類開發,符合 80/20 法則。
Spring JDBC通過實現DaoSupport來支持一致的數據庫訪問。
Spring JDBC提供如下DaoSupport實現:
- JdbcDaoSupport : 用于支持一致的JdbcTemplate訪問;
- NamedParameterJdbcDaoSupport: 繼承JdbcDaoSupport,同時提供NamedParameterJdbcTemplate訪問;
- SimpleJdbcDaoSupport : 繼承JdbcDaoSupport,同時提供SimpleJdbcTemplate訪問。
由于JdbcTemplate、NamedParameterJdbcTemplate、SimpleJdbcTemplate類使用DataSourceUtils獲取及釋放連接,而且連接是與線程綁定的,因此這些JDBC模板類是線程安全的,即JdbcTemplate對象可以在多線程中重用。
接下來看一下Spring JDBC框架的最佳實踐:
1) 首先定義Dao 接口
package cn.javass.spring.chapter7.dao;
import cn.javass.spring.chapter7.UserModel;
public interface IUserDao {
public void save(UserModel model);
public int countAll();
}2 )定義Dao 實現,此處是使用Spring JDBC 實現:
package cn.javass.spring.chapter7.dao.jdbc;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
import cn.javass.spring.chapter7.UserModel;
import cn.javass.spring.chapter7.dao.IUserDao;
public class UserJdbcDaoImpl extends SimpleJdbcDaoSupport implements IUserDao {
private static final String INSERT_SQL = "insert into test(name) values(:myName)";
private static final String COUNT_ALL_SQL = "select count(*) from test";
@Override
public void save(UserModel model) {
getSimpleJdbcTemplate().update(INSERT_SQL, new BeanPropertySqlParameterSource(model));
}
@Override
public int countAll() {
return getJdbcTemplate().queryForInt(COUNT_ALL_SQL);
}
} 此處注意首先Spring JDBC實現放在dao.jdbc包里,如果有hibernate實現就放在dao.hibernate包里;其次實現類命名如UserJdbcDaoImpl,即×××JdbcDaoImpl,當然如果自己有更好的命名規范可以遵循自己的,此處只是提個建議。
3 )進行資源配置(resources/chapter7/applicationContext-resources.xml ):
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:chapter7/resources.properties</value>
</list>
</property>
</bean>PropertyPlaceholderConfigurer用于替換配置元數據,如本示例中將對bean定義中的${…}占位符資源用“classpath:chapter7/resources.properties”中相應的元素替換。
<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource">
<bean class="org.logicalcobwebs.proxool.ProxoolDataSource">
<property name="driver" value="${db.driver.class}" />
<property name="driverUrl" value="${db.url}" />
<property name="user" value="${db.username}" />
<property name="password" value="${db.password}" />
<property name="maximumConnectionCount"
value="${proxool.maxConnCount}" />
<property name="minimumConnectionCount"
value="${proxool.minConnCount}" />
<property name="statistics" value="${proxool.statistics}" />
<property name="simultaneousBuildThrottle"
value="${proxool.simultaneousBuildThrottle}" />
<property name="trace" value="${proxool.trace}" />
</bean>
</property>
</bean>dataSource定義數據源,本示例使用proxool數據庫連接池,并使用LazyConnectionDataSourceProxy包裝它,從而延遲獲取數據庫連接;${db.driver.class}將被“classpath:chapter7/resources.properties”中的“db.driver.class”元素屬性值替換。
proxool數據庫連接池:本示例使用proxool-0.9.1版本,請到proxool官網下載并添加proxool-0.9.1.jar和proxool-cglib.jar到類路徑。
ProxoolDataSource屬性含義如下:
- driver:指定數據庫驅動;
- driverUrl:數據庫連接;
- username:用戶名;
- password:密碼;
- maximumConnectionCount:連接池最大連接數量;
- minimumConnectionCount:連接池最小連接數量;
- statistics:連接池使用樣本狀況統計;如1m,15m,1h,1d表示沒1分鐘、15分鐘、1小時及1天進行一次樣本統計;
- simultaneousBuildThrottle:一次可以創建連接的最大數量;
- trace:true表示被執行的每個sql都將被記錄(DEBUG級別時被打印到相應的日志文件);
4 )定義資源文件(classpath:chapter7/resources.properties ):
proxool.maxConnCount=10 proxool.minConnCount=5 proxool.statistics=1m,15m,1h,1d proxool.simultaneousBuildThrottle=30 proxool.trace=false db.driver.class=org.hsqldb.jdbcDriver db.url=jdbc:hsqldb:mem:test db.username=sa db.password=
用于替換配置元數據中相應的占位符數據,如${db.driver.class}將被替換為“org.hsqldb.jdbcDriver”。
5 )dao 定義配置(chapter7/applicationContext-jdbc.xml ):
<bean id="abstractDao" abstract="true">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="userDao"
class="cn.javass.spring.chapter7.dao.jdbc.UserJdbcDaoImpl"
parent="abstractDao"/>首先定義抽象的abstractDao,其有一個dataSource屬性,從而可以讓繼承的子類自動繼承dataSource屬性注入;然后定義userDao,且繼承abstractDao,從而繼承dataSource注入;我們在此給配置文件命名為applicationContext-jdbc.xml表示Spring JDBC DAO實現;如果使用hibernate實現可以給配置文件命名為applicationContext-hibernate.xml。
6) 最后測試一下吧(cn.javass.spring.chapter7. JdbcTemplateTest ):
@Test
public void testBestPractice() {
String[] configLocations = new String[] {
"classpath:chapter7/applicationContext-resources.xml",
"classpath:chapter7/applicationContext-jdbc.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);
IUserDao userDao = ctx.getBean(IUserDao.class);
UserModel model = new UserModel();
model.setMyName("test");
userDao.save(model);
Assert.assertEquals(1, userDao.countAll());
}首先讀取配置文件,獲取IUserDao接口實現,然后再調用IUserDao接口方法,進行數據庫操作,這樣對于開發人員使用來說,只面向接口,不關心實現,因此很容易更換實現,比如像更換為hibernate實現非常簡單。