mysql插入數據後返回自增ID的方法,last_insert_id(),selectkey

mysql插入數據後返回自增ID的方法
 
mysql和oracle插入的時候有一個很大的區別是,oracle支持序列作id,mysql自己有一個列能夠作自增加字段,mysql在插入一條數據後,如何能得到到這個自增id的值呢?
 
方法一:是使用last_insert_idjava

mysql> SELECT LAST_INSERT_ID();

    產生的ID 每次鏈接後保存在服務器中。這意味着函數向一個給定客戶端返回的值是該客戶端產生對影響AUTO_INCREMENT列的最新語句第一個 AUTO_INCREMENT值的。這個值不能被其它客戶端影響,即便它們產生它們本身的 AUTO_INCREMENT值。這個行爲保證了你可以找回本身的 ID 而不用擔憂其它客戶端的活動,並且不須要加鎖或處理。
 
    每次mysql_query操做在mysql服務器上能夠理解爲一次「原子」操做, 寫操做經常須要鎖表的, 是mysql應用服務器鎖表不是咱們的應用程序鎖表。
 
    值得注意的是,若是你一次插入了多條記錄,這個函數返回的是第一個記錄的ID值。
    由於LAST_INSERT_ID是基於Connection的,只要每一個線程都使用獨立的Connection對象,LAST_INSERT_ID函數 將返回該Connection對AUTO_INCREMENT列最新的insert or update*做生成的第一個record的ID。這個值不能被其它客戶端(Connection)影響,保證了你可以找回本身的 ID 而不用擔憂其它客戶端的活動,並且不須要加鎖。使用單INSERT語句插入多條記錄,  LAST_INSERT_ID返回一個列表。
    LAST_INSERT_ID 是與table無關的,若是向表a插入數據後,再向表b插入數據,LAST_INSERT_ID會改變。
 
方法二:是使用max(id)
 
使用last_insert_id是基礎鏈接的,若是換一個窗口的時候調用則會一直返回10
若是不是頻繁的插入咱們也可使用這種方法來獲取返回的id值mysql

select max(id) from user;

這個方法的缺點是不適合高併發。若是同時插入的時候返回的值可能不許確。
 
方法三:是建立一個存儲過程,在存儲過程當中調用先插入再獲取最大值的操做sql

複製代碼

DELIMITER $$
DROP PROCEDURE IF EXISTS `test` $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `test`(in name varchar(100),out oid int)
BEGIN
  insert into user(loginname) values(name);
  select max(id) from user into oid;
  select oid;
END $$
DELIMITER ;
call test('gg',@id);

複製代碼

方法四:使用@@identity數據庫

select @@IDENTITY

    @@identity是表示的是最近一次向具備identity屬性(即自增列)的表插入數據時對應的自增列的值,是系統定 義的全局變量。通常系統定義的全局變量都是以@@開頭,用戶自定義變量以@開頭。好比有個表A,它的自增列是id,當向A表插入一行數據後,若是插入數據 後自增列的值自動增長至101,則經過select @@identity獲得的值就是101。使用@@identity的前提是在進行insert操做後,執行select @@identity的時候鏈接沒有關閉,不然獲得的將是NULL值。服務器

方法五:是使用getGeneratedKeys()session

複製代碼

Connection conn = ;
Serializable ret = null;
PreparedStatement state = .;
ResultSet rs=null;
try {
    state.executeUpdate();
    rs = state.getGeneratedKeys();
    if (rs.next()) {
        ret = (Serializable) rs.getObject(1);
    }     
} catch (SQLException e) {
}
return ret;

複製代碼

總結一下,在mysql中作完插入以後獲取id在高併發的時候是很容易出錯的。另外last_insert_id雖然是基於session的可是不知道爲何沒有測試成功。
     
方法6:selectkey:併發

其實在ibtias框架裏使用selectkey這個節點,並設置insert返回值的類型爲integer,就能夠返回這個id值。oracle

SelectKey在Mybatis中是爲了解決Insert數據時不支持主鍵自動生成的問題,他能夠很隨意的設置生成主鍵的方式。app

無論SelectKey有多好,儘可能不要遇到這種狀況吧,畢竟很麻煩。框架

 

selectKey Attributes
屬性 描述
keyProperty selectKey 語句結果應該被設置的目標屬性。
resultType 結果的類型。MyBatis 一般能夠算出來,可是寫上也沒有問題。MyBatis 容許任何簡單類型用做主鍵的類型,包括字符串。
order 這能夠被設置爲 BEFORE 或 AFTER。若是設置爲 BEFORE,那麼它會首先選擇主鍵,設置 keyProperty 而後執行插入語句。若是設置爲 AFTER,那麼先執行插入語句,而後是 selectKey 元素-這和如 Oracle 數據庫類似,能夠在插入語句中嵌入序列調用。
statementType 和前面的相 同,MyBatis 支持 STATEMENT ,PREPARED 和CALLABLE 語句的映射類型,分別表明 PreparedStatement 和CallableStatement 類型。

 

SelectKey須要注意order屬性,像Mysql一類支持自動增加類型的數據庫中,order須要設置爲after纔會取到正確的值。

像Oracle這樣取序列的狀況,須要設置爲before,不然會報錯。

 

另外在用Spring管理事務時,SelectKey和插入在同一事務當中,於是Mysql這樣的狀況因爲數據未插入到數據庫中,因此是得不到自動增加的Key。取消事務管理就不會有問題。

 

下面是一個xml和註解的例子,SelectKey很簡單,兩個例子就夠了:

<insert id="insert" parameterType="map">  
    insert into table1 (name) values (#{name})  
    <selectKey resultType="java.lang.Integer" keyProperty="id">  
      CALL IDENTITY()  
    </selectKey>  
</insert>

上面xml的傳入參數是map,selectKey會將結果放到入參數map中。用POJO的狀況同樣,可是有一點須要注意的是,keyProperty對應的字段在POJO中必須有相應的setter方法,setter的參數類型還要一致,不然會報錯。

@Insert("insert into table2 (name) values(#{name})")  
@SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class)  
int insertTable2(Name name);

上面是註解的形式。

方法:7:使用<insert中的useGeneratedKeys 和keyProperty 兩個屬性

1.在Mybatis Mapper文件中添加屬性「useGeneratedKeys」和「keyProperty」,其中keyProperty是Java對象的屬性名,而不是表格的字段名

2.Mybatis執行完插入語句後,自動將自增加值賦值給對象systemBean的屬性id。所以,可經過systemBean對應的getter方法獲取!

【注意事項】

1.Mybatis Mapper 文件中,「useGeneratedKeys」和「keyProperty」必須添加,並且keyProperty必定得和java對象的屬性名稱一直,而不是表格的字段名

2.java Dao中的Insert方法,傳遞的參數必須爲java對象,也就是Bean,而不能是某個參數。

相關文章
相關標籤/搜索