欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Mybatis中怎么利用useGeneratedKeys獲取自增主鍵

Mybatis中怎么利用useGeneratedKeys獲取自增主鍵,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

創(chuàng)新互聯(lián)建站專業(yè)為企業(yè)提供澠池網(wǎng)站建設(shè)、澠池做網(wǎng)站、澠池網(wǎng)站設(shè)計(jì)、澠池網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、澠池企業(yè)網(wǎng)站模板建站服務(wù),10余年澠池做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

批量插入用戶收藏

for (tries = 0; tries < MAX_RETRY; tries++) { final int result = collectionMapper.insertCollections(collections); if (result == collections.size()) {  break; }}if (tries == MAX_RETRY) { throw new RuntimeSqlException("Insert collections error");}// 依賴數(shù)據(jù)庫(kù)生成的collectionidreturn collections;

collectionMapper.insertCollections 方法

<insert id="insertCollections" parameterType="list" useGeneratedKeys="true"  keyProperty="collectionId"> INSERT INTO collection( userid, item ) VALUES <foreach collection="list" item="collection" separator=",">  (#{collection.userId}, #{collection.item}) </foreach> ON DUPLICATE KEY UPDATE status = 0</insert>

不知道大家能不能發(fā)現(xiàn)其中的問題

分析

問題有兩個(gè)

返回值result的判斷錯(cuò)誤

使用on duplicate key 批量update返回影響的行數(shù)是和插入的數(shù)不一樣的。犯這種錯(cuò)主要在于想當(dāng)然,不看文檔

看下官網(wǎng)文檔

寫的很清楚

With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row, 2 if an existing row is updated, and 0 if an existing row is set to its current values. If you specify the CLIENT_FOUND_ROWS flag to the MySQL_real_connect() C API function when connecting to mysqld, the affected-rows value is 1 (not 0) if an existing row is set to its current values.

返回值有三種

0: 沒有更新 1 :insert 2. update

還有一個(gè)特殊情況,update 一個(gè)相同值到原來(lái)的值,這個(gè)根據(jù)客戶端配置,可能為0,可能為1。

所以這個(gè)判斷明顯錯(cuò)誤

利用批量InsertOrUpdate的userGeneratedKey來(lái)返回自增主鍵

這個(gè)問題批量插入時(shí)有update語(yǔ)句時(shí),就會(huì)發(fā)現(xiàn)有問題。返回的自增主鍵都是錯(cuò)的,這是為什么呢?

1. 首先我們看下mybatis對(duì)于useGeneratedKey的描述

>This tells MyBatis to use the JDBC getGeneratedKeys method to retrieve keys generated internally by the database (e.g. auto increment fields in RDBMS like MySQL or SQL Server). Default: false.

就是使用JDBC的getGeneratedKeys的方法來(lái)獲取的。

2. 我們?cè)僬蚁翵DBC的規(guī)范

Before version 3.0 of the JDBC API, there was no standard way of retrieving key values from databases that supported auto increment or identity columns. With older JDBC drivers for MySQL, you could always use a MySQL-specific method on the Statement interface, or issue the query SELECT LAST_INSERT_ID() after issuing an INSERT to a table that had an AUTO_INCREMENT key. Using the MySQL-specific method call isn't portable, and issuing a SELECT to get the AUTO_INCREMENT key's value requires another round-trip to the database, which isn't as efficient as possible. The following code snippets demonstrate the three different ways to retrieve AUTO_INCREMENT values. First, we demonstrate the use of the new JDBC 3.0 method getGeneratedKeys() which is now the preferred method to use if you need to retrieve AUTO_INCREMENT keys and have access to JDBC 3.0. The second example shows how you can retrieve the same value using a standard SELECT LAST_INSERT_ID() query. The final example shows how updatable result sets can retrieve the AUTO_INCREMENT value when using the insertRow() method.

意思就是JDBC3.0以前,有些亂七八糟的定義的,沒有統(tǒng)一,之后統(tǒng)一成了getGeneratedKeys()方法。兩邊是一致的。實(shí)現(xiàn)的原理主要就是數(shù)據(jù)庫(kù)端返回一個(gè)LAST_INSERT_ID。這個(gè)跟auto_increment_id強(qiáng)相關(guān)。

我們看下auto_increment_id的定義。重點(diǎn)關(guān)注批量插入

For a multiple-row insert, LAST_INSERT_ID() and mysql_insert_id() actually return the AUTO_INCREMENT key from the first of the inserted rows. This enables multiple-row inserts to be reproduced correctly on other servers in a replication setup.

批量插入的時(shí)候只會(huì)返回一個(gè)id,這個(gè)id值是第一個(gè)插入行的AUTO_INCREMENT值。至于為什么這么干,能夠使得mysql-server在master-slave架構(gòu)下也能保證id值統(tǒng)一的原因可以看下這篇。本篇文章就不展開了。

那么mysql server只返回一個(gè)id,客戶端批量插入的時(shí)候怎么能實(shí)現(xiàn)獲取全部的id呢

3. 客戶端的實(shí)現(xiàn)

我們看下客戶端getGeneratedKeys的實(shí)現(xiàn)。

JDBC com.mysql.jdbc.StatementImpl

public synchronized ResultSet getGeneratedKeys() throws SQLException {  if (!this.retrieveGeneratedKeys) {   throw SQLError.createSQLException(Messages.getString("Statement.GeneratedKeysNotRequested"), "S1009", this.getExceptionInterceptor());  } else if (this.batchedGeneratedKeys == null) {   // 批量走這邊的邏輯   return this.lastQueryIsOnDupKeyUpdate ? this.getGeneratedKeysInternal(1) : this.getGeneratedKeysInternal();  } else {   Field[] fields = new Field[]{new Field("", "GENERATED_KEY", -5, 17)};   fields[0].setConnection(this.connection);   return ResultSetImpl.getInstance(this.currentCatalog, fields, new RowDataStatic(this.batchedGeneratedKeys), this.connection, this, false);  } }

看下調(diào)用的方法 this.getGeneratedKeysInternal()

protected ResultSet getGeneratedKeysInternal() throws SQLException {    // 獲取影響的行數(shù)    int numKeys = this.getUpdateCount();    return this.getGeneratedKeysInternal(numKeys);  }

這里有個(gè)重要知識(shí)點(diǎn)了,首先獲取本次批量插入的影響行數(shù),然后再執(zhí)行具體的獲取id操作。

getGeneratedKeysInternal方法

protected synchronized ResultSet getGeneratedKeysInternal(int numKeys) throws SQLException {    Field[] fields = new Field[]{new Field("", "GENERATED_KEY", -5, 17)};    fields[0].setConnection(this.connection);    fields[0].setUseOldNameMetadata(true);    ArrayList rowSet = new ArrayList();    long beginAt = this.getLastInsertID();    // 按照受影響的范圍+遞增步長(zhǎng)    for(int i = 0; i < numKeys; ++i) {       if (beginAt > 0L) {            // 值塞進(jìn)去            row[0] = StringUtils.getBytes(Long.toString(beginAt));          }      beginAt += (long)this.connection.getAutoIncrementIncrement();    }}

迭代影響的行數(shù),然后依次獲取id。

所以批量insert是正確可以返回的。

但是批量insertOrUpdate就有問題了,批量insertOrUpdate的影響行數(shù)不是插入的數(shù)據(jù)行數(shù),可能是0,1,2這樣就導(dǎo)致了自增id有問題了。

比如插入3條數(shù)據(jù),2條會(huì)update,1條會(huì)insert,這時(shí)候updateCount就是5,generateid就會(huì)5個(gè)了,mybatis然后取前3個(gè)塞到數(shù)據(jù)里,顯然是錯(cuò)的。

以上是原理分析,如果想了解更詳細(xì)的實(shí)驗(yàn)結(jié)果,可以看下實(shí)驗(yàn)

總結(jié)

批量insert

<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>

來(lái)自官網(wǎng)的例子,mapper中不能指定@Param參數(shù),否則會(huì)有問題

批量insertOrUpdate

不能依賴useGeneratedKey返回主鍵。

關(guān)于Mybatis中怎么利用useGeneratedKeys獲取自增主鍵問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

文章標(biāo)題:Mybatis中怎么利用useGeneratedKeys獲取自增主鍵
當(dāng)前網(wǎng)址:http://www.chinadenli.net/article34/jcocse.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)云服務(wù)器企業(yè)建站網(wǎng)站營(yíng)銷搜索引擎優(yōu)化虛擬主機(jī)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名