1. 程式人生 > >Mybatis批量插入註解方式示例(oracle + mysql)

Mybatis批量插入註解方式示例(oracle + mysql)

場景:

匯入20萬條資料,for迴圈方式一條條插入巨慢(太low)。拼接長SQL的話,oracle根本無法支援(有SQL長度限制),經測試資料多於2000基本就不行了。故改用批量插入,在mapper中註解使用mybatis的foreach標籤寫。Mybatis框架會自動拼接生成批插的sql。


mysql版(這裡只寫2個欄位,大家自己照葫蘆畫瓢)

    @Insert(
            {   "<script>",
                    "insert into users ",
                    "(USERNAME,PASSWORD) ",
                    "VALUES",
                    "<foreach collection ='list' item='ulist' separator =','>",
                    "(#{ulist.username},#{ulist.password})",
                    "</foreach> ",
                "</script>"
            }
    )

    public void batch_insert(List<UserEntity> userList);

要點解析:

1. 註解的{} 中,長的SQL要換行的話,注意逗號和引號,每行內容在" "中。({}中內容是陣列,這個好理解)

2. <foreach>標籤中是迴圈拼接的語句,注意前後有(),欄位務必在括號裡

3. collection ='list'  標明傳入的資料是list型別的(還有其他的,請參閱官方文件)

4. item值不必與形參名字相同,它的作用可以這麼理解:形參的替身/別名,如下圖:

5. separator =','  說明要用什麼來分隔兩段語句(可以看oracle的例子,這裡有什麼不同)

最終拼接出來的語句如下(如果插入2行資料):

insert into users (username,password) values ('sam','123'),('tom','456');

oracle版:

    @Insert(
         {"<script>",
            "insert into users ",
            "(ID,username,password) ",
            "SELECT SEQ_USERS.NEXTVAL, A.* FROM (",
            "<foreach collection ='list' item='ulist' separator ='union all'>",
            "(SELECT #{ulist.username},#{ulist.password} FROM DUAL)",
            "</foreach> ) A",
            "</script>"
         }
    )

    public void batch_insert(List<UserEntity> userList);

比較複雜,使用了巢狀結構,多行語句之間使用union all連線。

特別注意,如果要插入序列,序列是要寫在foreach外的。


實際執行測試:

使用oracle,每批2000條commit一次為最佳。

換用mysql,可以20000條再commit一次,且速度比oracle快多了(同一臺機器測試)。