SpringBoot高級篇JdbcTemplate之數據更新與刪除

前面介紹了JdbcTemplate的插入數據和查詢數據,佔用CURD中的兩項,本文則將主要介紹數據更新和刪除。從基本使用上來看,姿式和前面的沒啥兩樣java

I. 環境準備

環境依然藉助前面一篇的配置,連接如: 190407-SpringBoot高級篇JdbcTemplate之數據插入使用姿式詳解git

或者直接查看項目源碼: github.com/liuyueyi/sp…github

咱們查詢所用數據,正是前面一篇插入的結果,以下圖spring

data

II. 更新使用說明

對於數據更新,這裏會分爲兩種進行說明,單個和批量;這個單個並非指只能一條記錄,主要針對的是sql的數量而言sql

1. update 方式

看過第一篇數據插入的童鞋,應該也能發現,新增數據也是用的這個方法,下面會介紹三種不一樣的使用姿式app

先提供一個數據查詢的轉換方法,用於對比數據更新先後的結果ide

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,執行便可spring-boot

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的方式,最大的好處有幾點ui

  • 能夠點對點的設置填充參數
  • PreparedStatementCreator 方式能夠獲取db鏈接,主動設置各類參數

下面給出兩個常見的使用方式

// 經過 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));
複製代碼

注意下第一種調用中,設置了超時時間,下面給出一個動圖,演示超時的使用姿式

show

在上圖中,

  • 首先是一個開啓一個事物,並修改了一條記錄,這個時候這條記錄會加上寫鎖
  • 而後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,經過一系列的修改,輸出以下

test result

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. 其餘

相關博文

2. 聲明

盡信書則不如,以上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激

QrCode
相關文章
相關標籤/搜索