JdbcTemplate 增刪查操作方法詳解

概述

在學習JdbcTemplate的時候比較迷迷糊糊,後來找到了一篇博客,介紹總結的非常好,讓我的學習找到了方向,也分享一下。這篇文章有自己學習實踐的一些例子,也有原博客的很多東西。

Spring JDBC抽象框架core包提供了JDBC模板類,其中JdbcTemplate是core包的核心類,所以其他模板類都是基於它封裝完成的,JDBC模板類是一種工作模式。

JdbcTemplate類通過模板設計模式幫助我們消除了冗長的代碼,只做需要做的事情(即可變部分),並且幫我們做哪些固定部分,如連接的創建及關閉。

JdbcTemplate類對可變部分採用回調接口方式實現,如ConnectionCallback通過回調接口返回給用戶一個連接,從而可以使用該連接做任何事情、StatementCallback通過回調接口返回給用戶一個Statement,從而可以使用該Statement做任何事情等等,還有其他一些回調接口
在這裏插入圖片描述
Spring除了提供JdbcTemplate核心類,還提供了基於JdbcTemplate實現的NamedParameterJdbcTemplate類用於支持命名參數綁定、 SimpleJdbcTemplate類用於支持Java5+的可變參數及自動裝箱拆箱等特性。

JdbcTemplate類支持的回調類:

預編譯語句及存儲過程創建回調:用於根據JdbcTemplate提供的連接創建相應的語句;

  • PreparedStatementCreator:通過回調獲取JdbcTemplate提供的Connection,由用戶使用該Conncetion創建相關的PreparedStatement;

  • CallableStatementCreator:通過回調獲取JdbcTemplate提供的Connection,由用戶使用該Conncetion創建相關的CallableStatement;

預編譯語句設值回調:用於給預編譯語句相應參數設值;

  • PreparedStatementSetter:通過回調獲取JdbcTemplate提供的PreparedStatement,由用戶來對相應的預編譯語句相應參數設值;

  • BatchPreparedStatementSetter:;類似於PreparedStatementSetter,但用於批處理,需要指定批處理大小;

自定義功能回調:提供給用戶一個擴展點,用戶可以在指定類型的擴展點執行任何數量需要的操作;

  • ConnectionCallback:通過回調獲取JdbcTemplate提供的Connection,用戶可在該Connection執行任何數量的操作;

  • StatementCallback:通過回調獲取JdbcTemplate提供的Statement,用戶可以在該Statement執行任何數量的操作;

  • PreparedStatementCallback:通過回調獲取JdbcTemplate提供的PreparedStatement,用戶可以在該PreparedStatement執行任何數量的操作;

  • CallableStatementCallback:通過回調獲取JdbcTemplate提供的CallableStatement,用戶可以在該CallableStatement執行任何數量的操作;

結果集處理回調:通過回調處理ResultSet或將ResultSet轉換爲需要的形式;

  • RowMapper:用於將結果集每行數據轉換爲需要的類型,用戶需實現方法mapRow(ResultSet rs, int rowNum)來完成將每行數據轉換爲相應的類型。

  • RowCallbackHandler:用於處理ResultSet的每一行結果,用戶需實現方法processRow(ResultSet rs)來完成處理,在該回調方法中無需執行rs.next(),該操作由JdbcTemplate來執行,用戶只需按行獲取數據然後處理即可。

  • ResultSetExtractor:用於結果集數據提取,用戶需實現方法extractData(ResultSet rs)來處理結果集,用戶必須處理整個結果集;

JdbcTemplate 增刪改CRUD操作方法

一. 增加、更新、刪除(一條SQL) (不需要參數)
  1. int update(String var1)
    其中sql參數爲需要傳入的SQL語句
  2. int update(PreparedStatementCreator var1)
public void test() {
        jdbcTemplate.update(new PreparedStatementCreator() {
            
            @Override
            public PreparedStatement createPreparedStatement(Connection conn)
                    throws SQLException {
                return conn.prepareStatement("insert into test(name) values('name1')");   
            }
        });
    }

3.int update(PreparedStatementCreator var1, KeyHolder var2)
此方法一般用來獲取新插入數據的主鍵ID,使用如下:

public void test() {
   KeyHolder keyHolder = new GeneratedKeyHolder(); 
   jdbcTemplate.update(new PreparedStatementCreator() {
       
       @Override
       public PreparedStatement createPreparedStatement(Connection conn)
               throws SQLException {
           
           return conn.prepareStatement("insert into test(name) values('name1')");  
            
       }
   },keyHolder);
   int i = keyHolder.getKey().intValue();//這就是剛插入的數據的主鍵
}
二. 增加、更新、刪除(一條SQL語句) (需要參數)
  1. int update(String sql,PreparedStatementSetter var2)
public void test() {
  String sql = "insert into test(name) values (?)";
  //返回的是更新的行數
  int count = jdbcTemplate.update(sql, new PreparedStatementSetter(){
      @Override
      public void setValues(PreparedStatement pstmt)
              throws SQLException {
          pstmt.setObject(1, "name4"); 
      }
    });
}
  1. int update(String sql, Object[] args, int[] var3)
    參數含義:sql:預處理SQL語句,args:需要注入的參數, argTypes:需要注入的sql參數的JDBC類型(java.sql.Types中來獲取類型的常量);
 public void test() {
   String sql = "insert into test(name,age,create_date) values (?,?,?)";
   Date now = new Date(System.currentTimeMillis());
   //返回的是更新的行數
   int count = jdbcTemplate.update(sql, new Object[]{"小明",14,now}, new int[]{Types.VARCHAR,Types.INTEGER,Types.DATE});
}
  1. int update(String sql, @Nullable Object… var2)
    其實內部還是調用方法a實現的,JdbcTemplate提供這種更簡單的方式“update(String sql, Object… args)”來實現設值,所以只要當使用該種方式不滿足需求時才應使用PreparedStatementSetter(上面方法1)
public void test() {
   String sql = "insert into test(name,age,create_date) values (?,?,?)";
    Date now = new Date(System.currentTimeMillis());
    //返回的是更新的行數
    int count = jdbcTemplate.update(sql, "小明", 14, now);
 }
public void test() {
  String sql = "insert into test(name,age,create_date) values (?,?,?)";
   Date now = new Date(System.currentTimeMillis());
   //返回的是更新的行數
   int count = jdbcTemplate.update(sql, new Object[]{"小明",14,now});
}

這兩種實際上調用的都是該方法,由此可見Object…args實際上就是可變的數組,而數組長度是固定的,必須先定義一個數組,而Object…args在傳遞時參數可以任意,所以也可以傳遞一個固定的Object數組。
4. int update(PreparedStatementCreator psc)
使用該方法可以自己使用原始jdbc方式給預編譯sql注入參數,來進行增加、刪除、更新操作:

public void addBlog(Blog blog) {
    String sql = "insert into blog(blogger_id,title,content,blog_type) values (?,?,?,?)";
    //返回的是更新的行數
    int count = template.update(new PreparedStatementCreator() {
        
        @Override
        public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
            PreparedStatement ps =conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
		    ps.setInt(1,blog.getBlogger_id());
		    ps.setString(2,blog.getTitle());
		    ps.setString(3,blog.getContent());
		    
            return ps;
        }
    });
}

如果需要返回插入的主鍵,只能用此方法,增加KeyHolder參數:

//添加博客,並返回新增博客的id
public int addBlog(Blog blog) {
   KeyHolder keyHolder = new GeneratedKeyHolder();
   String sql = "insert into blog(blogger_id,title,content,blog_type) values (?,?,?,?)";
   PreparedStatementCreator preparedStatementCreator = con -> {
       PreparedStatement ps = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
       ps.setInt(1,blog.getBlogger_id());
       ps.setString(2,blog.getTitle());
       ps.setString(3,blog.getContent());
       return ps;
   };
   template.update(preparedStatementCreator, keyHolder);
   int bloggerId = keyHolder.getKey().intValue();//獲取最終插入的自增的id
   return bloggerId;
}
三. 批量增、刪、更新數據(多條SQL數據)
  1. int[] batchUpdate(String… sql)
    批量執行SQL語句,SQL語句是固定的,但是SQL格式可以不一樣,不需要注入參數

    可以傳一個String數組,存放多條sql語句;返回值是int數組,即每條sql更新影響的行數。

  2. int[] batchUpdate(String sql, BatchPreparedStatementSetter pss)
    參數sql:一條預處理sql(如果是批量處理預處理sql,那麼sql的格式就是固定的,只填充參數而已);第二個參數就是回調類,前面有統一介紹回調類。

批量插入:
public void test(final List<Customer> customer) {//參數也是局部變量,也必須用final修飾,內部類中才能訪問(全局變量不用)
        
   String sql = "insert into test(name,age,create_date) values (?,?,?)";
   //返回的是更新的行數
   int[] count = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
       
       @Override
       public void setValues(PreparedStatement ps, int i)
               throws SQLException {
           //注入參數值
           ps.setString(1, customer.get(i).getName());
           ps.setInt(2, customer.get(i).getAge());
           ps.setDate(3, customer.get(i).getCreateDate());
       }
       
       @Override
       public int getBatchSize() {
           //批量執行的數量
           return customer.size();
       }
   });
}
批量更新:
public void test(final List<Customer> customer) {//參數也是局部變量,也必須用final修飾,內部類中才能訪問(全局變量不用)
  String sql = "update test set name = ?,age = ? where id = ?";
    //返回的是更新的行數
    int[] count = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
        
        @Override
        public void setValues(PreparedStatement ps, int i)
                throws SQLException {
            //注入參數值
            ps.setString(1, customer.get(i).getName());
            ps.setInt(2, customer.get(i).getAge());
            ps.setInt(3, customer.get(i).getId());
        }
        
        @Override
        public int getBatchSize() {
            //批量執行的數量
            return customer.size();
        }
    });
    
}
  1. 批量處理多條預處理sql語句還有下面幾種簡單方法(參數和前面類似,這裏就不詳解):
    int[] batchUpdate(String var1, List<Object[]> batchArgs)

    int[] batchUpdate(String var1, List<Object[]> var2, int[] argTypes)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章