成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MyBatis 批量操作的五個坑,千萬不要踩了!

數(shù)據(jù)庫 其他數(shù)據(jù)庫
批量操作往往隱藏著一些坑,使用不當(dāng),很可能會造成生產(chǎn)事故。今天來分享使用 MyBatis 批量操作可能會遇到的一些坑。

大家好,我是君哥。

在日常開發(fā)中,為了提高操作數(shù)據(jù)庫效率,我們往往會選擇批量操作,比如批量插入、批量更新,這樣可以減少程序和數(shù)據(jù)庫的交互,減少執(zhí)行時間。但是批量操作往往隱藏著一些坑,使用不當(dāng),很可能會造成生產(chǎn)事故。

今天來分享使用 MyBatis 批量操作可能會遇到的一些坑。下面我們以一張員工信息表為例進行講解,建表 SQL 如下(MySQL):

CREATE TABLE `staff` (
  `staff_id` tinyint(3) NOT NULL COMMENT '員工編號',
  `name` varchar(20) DEFAULT NULL COMMENT '員工姓名',
  `age` tinyint(3) DEFAULT NULL COMMENT '年齡',
  `sex` tinyint(1) DEFAULT '0' COMMENT '性別,0:男 1:女',
  `address` varchar(300) DEFAULT NULL COMMENT '家庭住址',
  `email` varchar(200) DEFAULT NULL COMMENT '郵件地址',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
  PRIMARY KEY (`staff_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

1.查詢條數(shù)

<select id="getStaffList" parameterType="int" resultType="Admin">
 select * from staff limit #{offset},50000
</select>

對應(yīng) Java 代碼如下:

public List<Staff> processStaffList(){
    int offset = 0;
    List<Staff> staffList = staffDao.getStaffList(offset);
    while(true){
        //...處理邏輯
        if(staffList.size() < 10000){
            break;
        }
        offset += 10000;
        staffList = staffDao.getStaffList(offset);
    }
}

上面的查詢想一次想查回 50000 條數(shù)據(jù),很有可能數(shù)據(jù)庫不能返回 50000 條。一般數(shù)據(jù)庫都有查詢結(jié)果集限制,比如 MySQL 會受兩個參數(shù)的限制:

  • max_allowed_packet,返回結(jié)果集大小,默認 4M,超過這個大小結(jié)果集就會被截斷;
  • max_execution_time,一次查詢執(zhí)行時間,默認值是 0 表示沒有限制,如果超過這個時間,MySQL 會終止查詢,返回結(jié)果。

所以,如果結(jié)果集太大不能全部返回,而我們在代碼中每次傳入的 offset 都是基于上次的 offset 加 50000,那必定會漏掉部分數(shù)據(jù)。

2.分頁問題

<select id="getStaffList" resultType="Staff">
 select * from staff limit #{offset},1000
</select>

如果單表數(shù)據(jù)量非常大,offset 會很大造成深度分頁問題,查詢效率低下。我們可以通過傳入一個起始的 staffId 來解決深度分頁問題。

我們修改一下 xml 中的代碼:

<select id="getStaffList" resultType="Staff">
 select * from staff 
  <if test="staffId != null">
        WHERE staff_id > #{staffId}
  </if>
 order by staff_id limit 1000
</select>

對應(yīng) Java 代碼如下:

public List<Staff> processStaffList(){
    List<Staff> staffList = staffDao.getStaffList(null);
    while(true){
        //...處理邏輯
        if(staffList.size() < 1000){
            break;
        }
        Staff lastStaffInPage = staffList.get(staffList.size() - 1);
        staffList = staffDao.getStaffList(lastStaffInPage.getStaffId());
 }
}

3.參數(shù)數(shù)量

下面看一下這一條插入 SQL:

<insert id="batchInsertStaff">
INSERT INTO staff (`staff_id`, `name`, `age`, `sex`, `address`, `email`) VALUES
 <foreach collection="staffList" index="" item="item" separator=",">
  (#{item.staffId,}, #{item.name},#{item.age},#{item.sex},#{item.address},#{item.email})
 </foreach>
</insert>

上面的代碼如果 staffList 數(shù)量太大,會導(dǎo)致整條語句參數(shù)過多。如果使用 Oracle 數(shù)據(jù)庫,參數(shù)數(shù)量超過 65535,會報 ORA-7445([opiaba]when using more than 65535 bind variables) 的錯誤,導(dǎo)致數(shù)據(jù)庫奔潰。一定要對參數(shù)數(shù)量進行限制。參數(shù)太多,也可能會拋出下面異常。

4.參數(shù)類型

上一節(jié)的代碼中,插入語句并沒有指定參數(shù)類型。這樣會有一個問題,雖然一個字段我們定義成可以為空,但是通過參數(shù)傳進來的這個字段值是空,就會拋出下面異常導(dǎo)致插入失敗。

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: 
ParameterMapping{property='_frch_item_50.name', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', 
expressinotallow='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting null for parameter #5 with JdbcType OTHER . 
Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: java.sql.SQLException: 無效的列類型: 1111

要保證程序健壯性,就要給插入語句中參數(shù)指定類型,上面代碼優(yōu)化后如下:

<insert id="batchInsertStaff">
    INSERT INTO staff (`staff_id`, `name`, `age`, `sex`, `address`, `email`) VALUES
 <foreach collection="staffList" index="" item="item" separator=",">
  (#{item.staffId,jdbcType=TINYINT}, #{item.name,jdbcType=VARCHAR},#{item.age,jdbcType=TINYINT},#{item.sex,jdbcType=TINYINT},#{item.address,jdbcType=VARCHAR},#{item.email,jdbcType=VARCHAR})
 </foreach>
</insert>

5.批量條數(shù)

批量操作是為了減少應(yīng)用和數(shù)據(jù)庫的交互,提高操作效率。但是如果對插入、更新這些批量操作不做條數(shù)限制,很可能會導(dǎo)致操作效率低下甚至數(shù)據(jù)庫 hang 住。我們可以通過分頁操作對批量條數(shù)做一些限制,看下面示例代碼:

public List<Staff> processStaffList(){
    List<Staff> staffList = ...;
    int pageSize = 500;
    int pageCount = staffList / pageSize;
    for(int i = 0; i < pageCount + 1; i++){
    List<Staff> subList = (i == pageCount)? staffList.subList(i * pageSize, staffList.size()) :
          staffList.subList(i * pageSize, (i + 1) * pageSize);
    staffDao.batchInsertStaff(subList);
    }
}

總結(jié)

作為一個 orm 框架,無論我們選擇 JDBC、MyBatis 還是 MyBatis-Plus,批量操作最終都是要操作底層數(shù)據(jù)庫,批次性能怎么樣、會不會出問題,主要還得參考底層數(shù)據(jù)庫的能力。因此,想用好批量,首先要了解數(shù)據(jù)庫的特性。

責(zé)任編輯:姜華 來源: 君哥聊技術(shù)
相關(guān)推薦

2024-04-10 08:39:56

BigDecimal浮點數(shù)二進制

2022-12-01 11:44:32

數(shù)據(jù)分析項目B2B

2025-04-29 10:17:42

2024-03-11 18:17:18

Python字符串分隔符

2024-02-04 08:26:38

線程池參數(shù)內(nèi)存

2023-08-03 07:13:59

2025-06-03 06:30:05

2022-11-18 07:34:12

Docker項目目錄

2025-03-28 08:40:00

C#異步編程

2016-11-10 13:32:08

網(wǎng)購詐騙雙11

2020-04-03 08:30:44

RabbitMQKafka軟件

2022-02-28 08:55:31

數(shù)據(jù)庫MySQL索引

2024-11-26 08:20:53

程序數(shù)據(jù)歸檔庫

2025-05-16 10:53:43

開發(fā)異步編程JavaScrip

2022-04-19 11:48:54

開發(fā)npm踩坑

2023-03-06 07:50:19

內(nèi)存回收Go

2024-05-06 00:00:00

緩存高并發(fā)數(shù)據(jù)

2012-03-14 14:25:57

2017-05-24 11:44:17

Linux命令

2019-04-03 14:03:58

Linux命令運行
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 日本涩涩网 | 国产精品一区二区三区在线 | 男女国产视频 | 欧美日本韩国一区二区三区 | 国产精品地址 | 亚洲国产在 | 久久伦理电影 | 一区二区三区四区国产 | 国产精品免费av | 欧美福利 | 九九综合| 欧美色综合天天久久综合精品 | 国产精品久久久久久久久久久久午夜片 | 中文字幕在线不卡 | 国产极品91 | 国产精品美女久久久久aⅴ国产馆 | 午夜精品久久 | 久久久久国产精品 | 亚洲综合久久久 | 成人依人 | 久草新在线 | 亚洲欧美一区二区三区在线 | a级网站 | 七七婷婷婷婷精品国产 | 天天躁人人躁人人躁狂躁 | 日韩一区二区三区四区五区 | 国产精品亚洲成在人线 | 久久99视频这里只有精品 | 久久99精品国产自在现线小黄鸭 | 成人国产精品 | 免费福利视频一区二区三区 | 久久网日本 | 福利视频一区二区 | 亚洲网站在线观看 | 久久久久一区二区 | 狠狠做深爱婷婷综合一区 | 激情黄色在线观看 | 国产精品免费在线 | 欧美群妇大交群中文字幕 | 成人一区二区三区在线观看 | 欧美日韩电影免费观看 |