190418-SpringBoot高階篇JdbcTemplate之資料更新與刪除
前面介紹了JdbcTemplate的插入資料和查詢資料,佔用CURD中的兩項,本文則將主要介紹資料更新和刪除。從基本使用上來看,姿勢和前面的沒啥兩樣
I. 環境準備
環境依然藉助前面一篇的配置,連結如: 190407-SpringBoot高階篇JdbcTemplate之資料插入使用姿勢詳解
或者直接檢視專案原始碼: https://github.com/liuyueyi/spring-boot-demo/blob/master/spring-boot/101-jdbctemplate
我們查詢所用資料,正是前面一篇插入的結果,如下圖
II. 更新使用說明
對於資料更新,這裡會分為兩種進行說明,單個和批量;這個單個並不是指只能一條記錄,主要針對的是sql的數量而言
1. update 方式
看過第一篇資料插入的童鞋,應該也能發現,新增資料也是用的這個方法,下面會介紹三種不同的使用姿勢
先提供一個數據查詢的轉換方法,用於對比資料更新前後的結果
private MoneyPO queryById(int id) { return jdbcTemplate.queryForObject( "select id, `name`, money, is_deleted as isDeleted, unix_timestamp(create_at) as " + "created, unix_timestamp(update_at) as updated from money where id=?", new BeanPropertyRowMapper<>(MoneyPO.class), id); }
a. 純sql更新
這個屬於最基本的方式了,前面幾篇博文中大量使用了,傳入一條完整的sql,執行即可
int id = 10; // 最基本的sql更新 String sql = "update money set money=money + 999 where id =" + id; int ans = jdbcTemplate.update(sql); System.out.println("basic update: " + ans + " | db: " + queryById(id));
b. 佔位sql
問好佔位,實際內容通過引數傳遞方式
// 佔位方式 sql = "update money set money=money + ? where id = ?"; ans = jdbcTemplate.update(sql, 888, id); System.out.println("placeholder update: " + ans + " | db: " + queryById(id));
c. statement
從前面的幾篇文章中可以看出,使用statement的方式,最大的好處有幾點
PreparedStatementCreator
下面給出兩個常見的使用方式
// 通過 PreparedStatementCreator 方式更新 ans = jdbcTemplate.update(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { // 設定自動提交,設定100ms的超時,這種方式最大的好處是可以控制db連線的引數 try { connection.setAutoCommit(true); connection.setNetworkTimeout(Executors.newSingleThreadExecutor(), 10); PreparedStatement statement = connection.prepareStatement("update money set money=money + ? where id " + "= ?"); statement.setInt(1, 777); statement.setInt(2, id); return statement; } catch (Exception e) { e.printStackTrace(); return null; } } }); System.out.println("statementCreator update: " + ans + " | db: " + queryById(id)); // 通過 PreparedStatementSetter 來設定佔位引數值 ans = jdbcTemplate.update(sql, new PreparedStatementSetter() { @Override public void setValues(PreparedStatement preparedStatement) throws SQLException { preparedStatement.setInt(1, 666); preparedStatement.setInt(2, id); } }); System.out.println("statementSetter update: " + ans + " | db: " + queryById(id));
注意下第一種呼叫中,設定了超時時間,下面給出一個動圖,演示超時的使用姿勢
在上圖中,
- 首先是一個開啟一個事物,並修改了一條記錄,這個時候這條記錄會加上寫鎖
- 然後JdbcTemplate中修改上面的這條記錄,嘗試加寫鎖,但是會失敗,所以一直阻塞,當超時之後,丟擲異常
2. batchUpdate 方式
批量方式,執行多個sql,從使用上看和前面沒有太大的區別,先給出一個查詢的通用方法
private List<MoneyPO> queryByIds(List<Integer> ids) { StringBuilder strIds = new StringBuilder(); for (Integer id : ids) { strIds.append(id).append(","); } return jdbcTemplate.query("select id, `name`, money, is_deleted as isDeleted, unix_timestamp(create_at) as " + "created, unix_timestamp(update_at) as updated from money where id in (" + strIds.substring(0, strIds.length() - 1) + ")", new BeanPropertyRowMapper<>(MoneyPO.class)); }
a. 純sql更新
// 批量修改, // 執行多條sql的場景 int[] ans = jdbcTemplate .batchUpdate("update money set money=1300 where id =10", "update money set money=1300 where id = 11"); System.out.println( "batch update by sql ans: " + Arrays.asList(ans) + " | db: " + queryByIds(Arrays.asList(10, 11)));
b. 佔位sql
// 佔位替換方式 ans = jdbcTemplate.batchUpdate("update money set money=money + ? where id = ?", Arrays.asList(new Object[]{99, 10}, new Object[]{99, 11})); System.out.println("batch update by placeHolder ans: " + Arrays.asList(ans) + " | db: " + queryByIds(Arrays.asList(10, 11)));
c. statement
// 通過 statement ans = jdbcTemplate .batchUpdate("update money set money=money + ? where id = ?", new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement preparedStatement, int i) throws SQLException { preparedStatement.setInt(1, 99); preparedStatement.setInt(2, i + 10); } @Override public int getBatchSize() { return 2; } }); System.out.println( "batch update by statement ans: " + Arrays.asList(ans) + " | db: " + queryByIds(Arrays.asList(10, 11)));
注意下上面的方法中, getBatchSize
返回實際的sql條數, setValues
中的i從0開始
3. 測試
原始資料中,money都是300,通過一系列的修改,輸出如下
III. 資料刪除
刪除的操作姿勢和上面基本一樣,也就是sql的寫法不同罷了,因此沒有太大的必要重新寫一篇,下面給出一個簡單的demo
@Component public class DeleteService { @Autowired private JdbcTemplate jdbcTemplate; public void delete() { int ans = jdbcTemplate.update("delete from money where id = 13"); System.out.println("delete: " + ans); } }
IV. 其他
相關博文
- 190407-SpringBoot高階篇JdbcTemplate之資料插入使用姿勢詳解
- 190412-SpringBoot高階篇JdbcTemplate之資料查詢上篇
- 190417-SpringBoot高階篇JdbcTemplate之資料查詢下篇
0. 專案
- 工程: https://github.com/liuyueyi/spring-boot-demo
- 專案: https://github.com/liuyueyi/spring-boot-demo/blob/master/spring-boot/101-jdbctemplate
1. 一灰灰Blog
- 一灰灰Blog個人部落格 https://blog.hhui.top
- 一灰灰Blog-Spring專題部落格 http://spring.hhui.top
一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛
2. 宣告
盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
- 微博地址:小灰灰Blog
- QQ: 一灰灰/3302797840
3. 掃描關注
一灰灰blog
知識星球
打賞 如果覺得我的文章對您有幫助,請隨意打賞。