MyBatis真的支持批量插入並返回各自的主鍵嗎?


筆者觀點:

:各位,mybatis支持批量插入並返回各自的主鍵嗎?java

:首先、mybatis是支持批量插入的,可是、並非都能返回各自的主鍵值;注意:我這裏用了「並非都」,也就是說有些狀況下的主鍵是能正常返回其主鍵的,而另一些狀況下的主鍵則是不行的;那麼什麼狀況下能正常返回,什麼狀況下不能正常返回呢?mysql

這裏須要注意的是對於單條數據插入:不管是自增或者其餘方式自主生成的主鍵mybatis都是支持返回。
web

對於批量插入而言:sql

一、能正常返回其主鍵的,也就是mybatis支持的經過自增主鍵的返回。數據庫

二、不能正常返回其主鍵的,應該就是相似MySQL 的經過UUID來生成的主鍵mybatis貌似不支持將其返回。apache



觀點闡述:

針對mybatis支持的能夠追溯其官方介紹:數組

一、單條插入(自增主鍵)的支持:並返回自增的主鍵微信

首先,若是你的數據庫支持自動生成主鍵的字段(好比 MySQL 和 SQL Server),那麼你能夠設置 useGeneratedKeys=」true」,而後再把 keyProperty 設置到目標屬性上就 OK 了。例如,若是 Author 表已經對 id 使用了自動生成的列類型,那麼語句能夠修改成:網絡


<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id"> insert into Author (username,password,email,bio) values (#{username},#{password},#{email},#{bio})</insert>
<!-- 或者 -->
<insert id="insertAuthor"> <!-- 將插入數據的主鍵返回,返回到Author對象中 SELECT LAST_INSERT_ID():獲得剛insert進去記錄的主鍵值,只適用於自增主鍵 keyProperty:將查詢到的主鍵值設置到parameterType指定的對象的哪一個屬性 order:SELECT LAST_INSERT_ID()執行順序,相對於insert語句來講它的執行順序 resultType:指定 SELECT LAST_INSERT_ID()返回的結果類型 --> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> SELECT LAST_INSERT_ID() </selectKey> insert into Author (username,password,email,bio) values (#{username},#{password},#{email},#{bio}) </insert>


二、單條插入(非自增主鍵)的支持:並返回自主生成的主鍵mybatis

對於不支持自動生成類型的數據庫或可能不支持自動生成主鍵的 JDBC 驅動,MyBatis 有另一種方法來生成主鍵。


<insert id="insertAuthor"> <!--  使用mysql的uuid()函數生成主鍵 執行順序: 先經過UUID()查詢到主鍵,將主鍵輸入到sql語句中 執行UUID()順序相對於insert語句以前執行 --> <selectKey keyProperty="id" resultType="int" order="BEFORE"> select REPLACE(UUID(),'-','') </selectKey> insert into Author (id, username, password, email,bio, favourite_section) values (#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})</insert>


在上面的示例中,selectKey 元素中的語句將會首先運行,Author 的 id 會被設置,而後插入語句會被調用。這能夠提供給你一個與數據庫中自動生成主鍵相似的行爲,同時保持了 Java 代碼的簡潔。


三、批量插入(自增主鍵)的支出:並返回自增各自主鍵

若是你的數據庫還支持多行插入, 你也能夠傳入一個 Author 數組或集合,並返回自動生成的主鍵。


<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id"> insert into Author (username, password, email, bio) values <foreach item="item" collection="list" separator=","> (#{item.username}, #{item.password}, #{item.email}, #{item.bio}) </foreach></insert>


四、批量插入(非自增主鍵)的支出:嘗試沒法返回其各自主鍵

嘗試錯誤的code以下:


<insert id="insertAuthor" > <selectKey keyProperty="id" resultType="int" order="BEFORE"> select REPLACE(UUID(),'-','') </selectKey> insert into Author (id, username, password, email, bio) values <foreach item="item" collection="list" separator=","> (#{id}, #{item.username}, #{item.password}, #{item.email}, #{item.bio}) </foreach></insert>


若有好的解決辦法勞煩加我wx:W828013910 告知,提早謝過!



原理探究:

既然咱們已經瞭解了上面的幾種狀況,至於爲何能夠支持自增主鍵返回,和不支持非自增主鍵的返回咱們接着探究下「mybatis獲取主鍵ID實現原理」應該會有更深刻一些的理解。

首先、須要注意的是,不論在xml映射器仍是在接口映射器中,添加記錄的主鍵值並不是是添加操做的返回值。實際上,在MyBatis中執行添加操做時只會返回當前添加的記錄數。

底層源碼實現以下:


package org.apache.ibatis.executor.statement;public class PreparedStatementHandler extends BaseStatementHandler { @Override public int update(Statement statement) throws SQLException { PreparedStatement ps = (PreparedStatement) statement; // 真正執行添加操做的SQL語句 ps.execute(); int rows = ps.getUpdateCount(); Object parameterObject = boundSql.getParameterObject(); // 返回數據庫生成的自增主鍵值,而不是生成數據庫的自增主鍵值。 KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); // 在執行添加操做完畢以後,再處理記錄主鍵字段值 keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);  // 添加記錄時返回的是記錄數,而並不是記錄的主鍵字段值 return rows; }}

關於源碼的更多實現細節可參考(Mybatis之KeyGenerator)


順便看一下MyBatis添加操做的時序圖:

跟蹤時序圖執行步驟能夠看到,MyBatis最終是經過MySQL驅動程序獲取到了新添加的記錄主鍵值。




總結概括:

對於上面 3 可能具體使用時還會遇到一些問題,一些建議性的解決辦法以下(來源網絡):

一、嘗試升級mybatis的版本到3.3.1以上,官方是在這個版本中才加入了批量插入返回其各自自增主鍵id的功能。

二、在Dao中不能使用@Param註解。

三、Mapper.xml中使用list變量(parameterType="java.util.List")接受Dao中的參數集合。

四、還有觀點提出多是mybatis的一個bug,具體可參考(Mybatis之foreach批量insert,返回主鍵id列表(修復Mybatis返回null的bug))


對於上面的4 如何讀者有好的解決辦法,還望不吝賜教!!!


·end·

—若是喜歡,快分享給你的朋友們吧—




有任何問題、意見等 請在公衆號內留言

你點的每一個贊,我都認真當成了喜歡

本文分享自微信公衆號 - 一隻藍色猿(umizhang0910)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索