Spring JDBC Framework詳解——批量JDBC操作、ORM映射
作者:niumd,轉載請注明出處,謝謝
發(fā)表時間:2010 年 03 月 17 日
原文鏈接:http://ari.iteye.com/admin/blogs/618449
一、Spring JDBC 概述
Spring 提供了一個強有力的模板類JdbcTemplate簡化JDBC操作,DataSource,JdbcTemplate都可以以Bean的方式定義在想xml配置文件,JdbcTemplate創(chuàng)建只需注入一個DataSource,應用程序Dao層只需要繼承JdbcDaoSupport, 或者注入JdbcTemplate,便可以獲取JdbcTemplate,JdbcTemplate是一個線程安全的類,多個Dao可以注入一個JdbcTemplate;
<!-- Oracle數(shù)據(jù)源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@oracle.devcake.co.uk:1521:INTL"/> <property name="username" value="sa"/> <property name="password" value=""/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!-- set注入方式獲取jdbcTemplate --> <bean id="customerDao" class="JdbcCustomerDao" > <property name="jdbcTemplate" ref="jdbcTemplate"/> </bean> <!-- 注入dataSource,customerDao通過繼承JdbcDaoSupport ,使用this.getJdbcTemplate()獲取JdbcTemplate --> <bean id="customerDao" class="JdbcCustomerDao" > <property name="dataSource" ref="dataSource"/> </bean>
然后將jdbcTemplate對象注入自定義的Dao、或者繼承JdbcDaoSupport,例如:
public class JdbcCustomerDao extends JdbcDaoSupport implements CustomerDao { } public class JdbcCustomerDao implements CustomerDao { private JdbcTemplate jdbcTemplate public void setJdbcTemplate()JdbcTemplate jdbcTemplate{ this.jdbcTemplate=jdbcTemplate } }
二、 JdbcTemplate 提供以下主要方法簡化JDBC操作:
2.1、List query(String sql,Ojbect[] args,RowMapper rowMapper)
說明:常用的查詢,sql待執(zhí)行的sql語句,args是sql語句的參數(shù),rowMapper負責將每一行記錄轉化為java對象存放在list,并最終返回,例如:
public List<Book> queryByAuthor(String author) { String sql = "select * from book where author=?"; Collection c = getJdoTemplate().find(sql, new Object[] { author },new BookRowMapper()); List<Book> books = new ArrayList<Book>(); books.addAll(c); return books; } class BookRowMapper implements RowMapper{ public Object mapRow(ResultSet res, int index) throws SQLException { Book book = new Book(); book.setId(rs.getInt("id")); //省略set return book; } }
更新、刪除、其他查詢操作類似,舉例如下,詳細細節(jié)請參考spring api:
//返回值為一個長整形 public long getAverageAge() { return getJdbcTemplate().queryForLong("SELECT AVG(age) FROM employee"); } //返回一個整數(shù) public int getTotalNumberOfEmployees() { return getJdbcTemplate().queryForInt("SELECT COUNT(0) FROM employees"); } //更新操作 this.jdbcTemplate.update( "insert into t_actor (first_name, surname) values (?, ?)", new Object[] {"Leonor", "Watling"});
2.2、spring 2.5新功能,另類的jdbc ORM:BeanPropertyRowMapper
上面我們檢索時必須實現(xiàn)RowMapper,將結果集轉化為java對象。Spring2.5 簡化了這一操作,使得我們不必再實現(xiàn)RowMapper,實現(xiàn)此功能的倆個神奇東東便是:ParameterizedRowMapper,ParameterizedBeanPropertyRowMapper,貌似通過java反射機制實現(xiàn)了將resultset字段映射到java對象,但是數(shù)據(jù)表的列必須和java對象的屬性對應,沒有研究源碼,有點類似于apache 的BeanUtil,不知為何這部分在spring開發(fā)參考手冊沒有,難道不是經(jīng)典。
//使用ParameterizedBeanPropertyRowMapper @SuppressWarnings({"unchecked"}) public List<Customer> getAll() { return getJdbcTemplate().query("select * from t_customer", ParameterizedBeanPropertyRowMapper.newInstance(Customer.class)); } //使用BeanPropertyRowMapper @SuppressWarnings({"unchecked"}) public List<Customer> getAll() { return getJdbcTemplate().query("select * from t_customer", new BeanPropertyRowMapper(Customer.class)); }
注意:ParameterizedBeanPropertyRowMapper是BeanPropertyRowMapper子類。另外表的字段名稱必須和實體類的成員變量名稱一致;
2.3、spring之JDBC批量操作
jdbcTemplate.batchUpdate(final String[] sql) ,API解釋:Issue multiple SQL updates on a single JDBC Statement using batching,翻譯過來大致為:解決多個sql的插入、更新、刪除操作在一個Statement中。性能一般。
jdbcTemplate.batchUpdate(String sql, final BatchPreparedStatementSetter pss),類似于JDBC的PreparedStatement,性能較上著有所提高。
我們舉例說明如何使用,示例如下:
final int count = 2000; final List<String> firstNames = new ArrayList<String>(count); final List<String> lastNames = new ArrayList<String>(count); for (int i = 0; i < count; i++) { firstNames.add("First Name " + i); lastNames.add("Last Name " + i); } jdbcTemplate.batchUpdate( "insert into customer (id, first_name, last_name, last_login, comments) values (?, ?, ?, ?, ?)", new BatchPreparedStatementSetter() { //為prepared statement設置參數(shù)。這個方法將在整個過程中被調用的次數(shù) public void setValues(PreparedStatement ps, int i) throws SQLException { ps.setLong(1, i + 10); ps.setString(2, firstNames.get(i)); ps.setString(3, lastNames.get(i)); ps.setNull(4, Types.TIMESTAMP); ps.setNull(5, Types.CLOB); } //返回更新的結果集條數(shù) public int getBatchSize() { return count; } }); }
BatchSqlUpdate類是SqlUpdate 的子類,適用于插入、刪除、更新批量操作,內部使用PreparedStatement,所以效率很高,批量語句達到設定的batchSize,或者手動調用flush才會執(zhí)行批量操作。注意:此類是非線程安全的,必須為每個使用者創(chuàng)建一個實例,或者在同一個線程中使用前調用reset。
下面我們舉例說明如何使用BatchSqlUpdate,來執(zhí)行批量操作。示例如下:
class BatchInsert extends BatchSqlUpdate { private static final String SQL = "insert into t_customer (id, first_name, last_name, last_login, " + "comments) values (?, ?, ?, ?, null)"; BatchInsert(DataSource dataSource) { super(dataSource, SQL); declareParameter(new SqlParameter(Types.INTEGER)); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.VARCHAR)); declareParameter(new SqlParameter(Types.TIMESTAMP)); setBatchSize(10); } }
int count = 5000; for (int i = 0; i < count; i++) { batchInsert.update(new Object[] { i + 100L, "a" + i, "b" + i, null }); }
至此,spring JDBC主要的應用基本上都簡單羅列一番,所有代碼均為文章舉例,不是很嚴謹,僅為演示每一種用法,拋磚引玉,希望有獨特見解的拍磚,有問題的請指明問題所在,謝謝
posted on 2011-05-10 21:06 空白 閱讀(3274) 評論(0) 編輯 收藏 所屬分類: Java