NamedParameterJdbcTemplate中包含了一個JdbcTemplate,NamedParameterJdbcTemplate中的很多方法實際上還是交由JdbcTemplate去完成。NamedParameterJdbcTemplate較JdbcTemplate增加的功能是對輸入的條件參數取別名。例如:
String sql2 = "select id,tname as name,tpwd as password from tadd where tname = :name";將查詢參數中數據庫的列名tname換成了name。
SimpleJdbcTemplate中包含了一個NamedParameterJdbcTemplate,SimpleJdbcTemplate中的很多實現是交由了底層的JdbcTemplate去完成。SimpleJdbcTemplate所增強的功能是泛型和可變長度的參數。
Spring 3.1版本之后,NamedParameterJdbcTemplate和JdbcTemplate也支持了泛型,SimpleJdbcTemplate就被標注為了過時。但是在Spring 3.1版本之前,能使用SimpleJdbcTemplate還是要使用SimpleJdbcTemplate。
SimpleJdbcTemplate中的主要方法如下:
mysql> desc tadd;
+-------+------------------------+--------+--------+-------------+------------------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------------------+-----------+--------+--------------+-----------------------------------+
| id | bigint(255) | NO | PRI | | auto_increment |
| tname | varchar(300) | YES | | NULL | |
| tpwd | varchar(300) | YES | | NULL | | |
+-----------+--------------------+---------+--------+---------------+-----------------------------------+
mysql> insert into tadd(tname,tpwd) values ('apply','asure');
首先來看只返回一條記錄的查詢操作,返回多條記錄將失敗。
使用queryForObject方法及其重載的方法
1. 沒有JavaBean時的操作,使用queryForObject(String sql, RowMapper<T> rm, Map<String, ?> args):
String sql2 = "select id,tname as name,tpwd as password from tadd where tname = :n"; RowMapper<UserBean> rw = new RowMapper<UserBean>(){ @Override public UserBean mapRow(ResultSet paramResultSet, int paramInt) throws SQLException { UserBean ub = new UserBean(); ub.setId(paramResultSet.getObject("id") + ""); ub.setName(paramResultSet.getObject("name") + ""); ub.setPassword(paramResultSet.getObject("password") + ""); return ub; } }; Map<String, String> map = new HashMap<String, String>(); map.put("n", "apply"); UserBean ub = jdbctemplate.queryForObject(sql2, rw, map);
查詢語句中as后面的名稱是別名,會將查詢結果中數據庫的列名替換為別名。tname = :n條件參數取別名有二個作用,一是可以作用於Map參數,第二個是作用於下面的BeanPropertySqlParameterSource,使用BeanPropertySqlParameterSource時別名要和JavaBean中的名稱一致。
2.也可以使用可變長度的參數,這時條件參數不能取別名,要使用占位符的形式:
String sql2 = "select id,tname as name,tpwd as password from tadd where tname = ?";
UserBean ub = jdbctemplate.queryForObject(sql2, rw, "apply");
3.創建一個名為UserBean的JavaBean,屬性為id,name和password,對應屬性有get和set方法。
使用方法:T queryForObject(String sql, ParameterizedRowMapper<T> rm, Map<String, ?> args)
UserBean ub = jdbctemplate.queryForObject(sql2, new BeanPropertyRowMapper(UserBean.class),map);
可以使用可變長度的參數,這時sql中也同樣條件參數不能取別名:
UserBean ub = jdbctemplate.queryForObject(sql2, new BeanPropertyRowMapper(UserBean.class),"apply");
4.還可以將Map參數替換,采用完全的面向對象的方式:
String sql2 = "select id,tname as name,tpwd as password from tadd where tname = :name"; userb.setName("apply"); UserBean ub = jdbctemplate.queryForObject(sql2, new BeanPropertyRowMapper(UserBean.class),new BeanPropertySqlParameterSource(userb));
注意:使用BeanPropertySqlParameterSource時別名要和JavaBean中的名稱一致,否則會出錯,和第一種情況比較。
5.查詢結果又多條時,可以使用query,queryForList或者queryForMap,只要弄清楚參數中的ParameterizedRowMapper和SqlParameterSource即可。
查詢結果為基本類型或者String型時,可以使用queryForObject, queryForInt等。
查詢的操作使用各種的query重載方法,增加、刪除、修改的操作使用各種的update重載方法,使用類似。
還有就是批量修改使用batchUpdate的各種重載方法。
6. NamedParameterJdbcTemplate中的各方法與SimpleJdbcTemplate類似,可能參數的順序會不太一樣。有下面幾個有用的方法:
用KeyHolder獲取新插入數據的主鍵值,可以是單一主鍵或者是聯合主鍵。
String sql3 = "insert into tadd(tname) values (:name)"; UserBean userb = new UserBean(); userb.setName("applyee"); KeyHolder kh = new GeneratedKeyHolder(); jdbctemplate.update(sql3, new BeanPropertySqlParameterSource(userb), kh); userb.setId(kh.getKey().intValue()+ "");
7.行映射器ResultSetExtractor,RowCallbackHandler,RowMapper。
RowMapper前面已經用到,應用起來也最為簡單,只需要處理單行數據即可。
String sql4 = "select id,tname as name,tpwd as password from tadd where id < :id"; RowMapper<UserBean> rw = new RowMapper<UserBean>(){ @Override public UserBean mapRow(ResultSet paramResultSet, int paramInt) throws SQLException { UserBean ub = new UserBean(); ub.setId(paramResultSet.getObject("id") + ""); ub.setName(paramResultSet.getObject("name") + ""); ub.setPassword(paramResultSet.getObject("password") + ""); return ub; } }; UserBean user = new UserBean(); user.setId("4"); List<UserBean> users = jdbctemplate.query(sql4, new BeanPropertySqlParameterSource(user), rw); for(UserBean u: users){ System.out.println(u); }
RowCallbackHandler需要自己處理每行的數據
final List<UserBean> userList = new ArrayList<UserBean>(); RowCallbackHandler rch = new RowCallbackHandler(){ @Override public void processRow(ResultSet paramResultSet) throws SQLException { UserBean ub = new UserBean(); ub.setId(paramResultSet.getObject("id") + ""); ub.setName(paramResultSet.getObject("name") + ""); ub.setPassword(paramResultSet.getObject("password") + ""); userList.add(ub); } }; UserBean user = new UserBean(); user.setId("4"); jdbctemplate.query(sql4, new BeanPropertySqlParameterSource(user), rch); for(UserBean u: userList){ System.out.println(u); }
ResultSetExtractor也需要自己處理結果集:
ResultSetExtractor rse = new ResultSetExtractor(){ public Object extractData(ResultSet rs) throws SQLException, DataAccessException { List<UserBean> userList = new ArrayList<UserBean>(); while(rs.next()){ UserBean ub = new UserBean(); ub.setId(rs.getObject("id") + ""); ub.setName(rs.getObject("name") + ""); ub.setPassword(rs.getObject("password") + ""); userList.add(ub); } return userList; } }; UserBean user = new UserBean(); user.setId("4"); List<UserBean> ul = jdbctemplate.query(sql4, new BeanPropertySqlParameterSource(user), rse); for(UserBean u: ul){ System.out.println(u); }
8.還可以使用回調函數的方式來實現,相當於自己可以使用JDBC重寫代碼,而不是使用封裝好的方法:
sql語句的回調,使用PreparedStatementCallback返回已經編譯好的sql語句再進行處理
test.execute("update xx set name = 'oo' where id= ?", new PreparedStatementCallback(){ public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { ps.setString(1, "123");//這里的參數對應? ps.addBatch(); ps.setString(1, "456"); ps.addBatch(); return ps.executeBatch(); } });
連接的回調execute(ConnectionCallback<T> action)
9. 通過JDBCTemplate操作數據庫,鏈接是不需要手動地關閉的,但是如果從JDBCTemplate中獲取了鏈接則需要手動地去關閉鏈接。
例如,jdbcTemplate.getDataSource().getConnection()就需要自己去關閉數據庫鏈接,否則會導致嚴重的后果。
DataSourceUtils.releaseConnection(con, getDataSource());