對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實現非常簡單。