Java MyBatis 插入數據庫返回主鍵

問題?

如何在Java MyBatis 插入數據庫返回主鍵?java

最近在搞一個電商系統中因爲業務需求,須要在插入一條產品信息後返回產品Id,剛開始遇到一些坑,這裏作下筆記,以防從此忘記。數據庫

相似下面這段代碼同樣獲取插入後的主鍵緩存

User user = new User();  
user.setUserName("chenzhou");  
user.setPassword("xxxx");  
user.setComment("測試插入數據返回主鍵功能");  
  
System.out.println("插入前主鍵爲:"+user.getUserId());  
userDao.insertAndGetId(user);//插入操做  
System.out.println("插入後主鍵爲:"+user.getUserId());  

解決方案:

因爲鄙人當時的學習水平有限,未能很好處理這個問題,現在再來看這個問題,其實很簡單。session

當時個人思惟侷限於插入數據後不想再次調用查詢接口,就直接獲取這個插入的主鍵Id. 所以若是想達到這種效果,最優方案是下面解決方案的第二種方式mybatis

 可是其實咱們徹底能夠在插入後再調用下其餘查詢接口就能夠了。app

User user = new User();  
user.setUserName("chenzhou"); user.setPassword("xxxx"); user.setComment("測試插入數據返回主鍵功能"); System.out.println("插入前主鍵爲:"+user.getUserId()); userDao.insertAndGetId(user);//插入操做  User myUser=userDao.findUserByName(user.getName()); System.out.println("插入後主鍵爲:"+myUser.getUserId()); 

不想再次調用查詢接口的解決方案

通過查詢網上資料,發現大體有兩種方式。dom

第一種方式:

在實體類的映射文件 "*Mapper.xml" 這樣寫:ide

<insert id="insertAndGetId" useGeneratedKeys="true" keyProperty="userId" parameterType="com.chenzhou.mybatis.User">
    insert into user(userName,password,comment)
    values(#{userName},#{password},#{comment})
</insert>

Tips:學習

useGeneratedKeys="true" 表示給主鍵設置自增加
keyProperty="userId"  表示將自增加後的Id賦值給實體類中的userId字段。
parameterType="com.chenzhou.mybatis.User" 這個屬性指向傳遞的參數實體類

這裏提醒下,<insert></insert> 中沒有resultType屬性,不要亂加。

實體類中uerId 要有getter() and setter(); 方法

因爲我在MySQL數據庫中建表時候已經設置了字段自增加,故最終我選擇了第二種方式。測試

第二種方式

一樣在實體類的映射文件 "*Mapper.xml" 可是要這樣寫:

    <!-- 插入一個商品 -->
    <insert id="insertProduct" parameterType="domain.model.ProductBean" >
       <selectKey resultType="java.lang.Long" order="AFTER" keyProperty="productId">
          SELECT LAST_INSERT_ID()
      </selectKey>
        INSERT INTO t_product(productName,productDesrcible,merchantId)values(#{productName},#{productDesrcible},#{merchantId});
    </insert>

Tips: 

<insert></insert> 中沒有resultType屬性,可是<selectKey></selectKey> 標籤是有的。

order="AFTER" 表示先執行插入語句,以後再執行查詢語句。

可被設置爲 BEFORE 或 AFTER。

若是設置爲 BEFORE,那麼它會首先選擇主鍵,設置 keyProperty 而後執行插入語句。

若是設置爲 AFTER,那麼先執行插入語句,而後是 selectKey 元素-這和如 Oracle 數據庫類似,能夠在插入語句中嵌入序列調用
keyProperty="userId"  表示將自增加後的Id賦值給實體類中的userId字段。

SELECT LAST_INSERT_ID() 表示MySQL語法中查詢出剛剛插入的記錄自增加Id.

實體類中uerId 要有getter() and setter(); 方法
實現需求,上面那些就足夠了。

瞭解擴展

這裏若是有興趣的,請繼續聽我講一個Mybatis中可能誤入的坑。

爲何Mybatis 中修改添加方法爲有返回值後,雖然提示插入數據庫成功而且也能讀取插入的數據,可是當你打開數據庫後就是看不到插入的數據?

若是在實現上述需求時,想插入後返回主鍵的話,切記不要這樣寫。
 @Override public Long insertProduct(ProductBean productBean) { // TODO Auto-generated method stub
        SqlSession session = MybatisJDBCUtil.currentSession(); ProductIDao productIDao = session.getMapper(ProductIDao.class);// 這裏*.class // 必須對應DAO的接口層
        return productIDao.insertProduct(productBean); }

Why?

由於若是你是像上面這樣寫,那麼執行後返回的也不是你想要的主鍵Id,而是執行數據庫語句後受影響的行數。

並且,當你執行後你會發現提示插入成功,你用代碼也能夠讀取出插入的數據,可是永遠只有一條記錄。

而且,你打開數據庫會發現,數據庫中沒有插入成功任何數據。

我在這裏鬱悶了N久,終於發現了關鍵所在。

有返回值和沒返回值的區別在於:

有返回值的只是對數據庫只讀模式訪問數據庫,對數據庫數據不會有任何修改,好比各類方式的查詢。

無返回值的則會以讀寫模式訪問數據庫,會對數據庫中的數據進行修改,好比刪除,增長。

除此以外,根據我的理解應該mybatis在執行插入語句時會先緩存到構造的一個相似session集合中,而後纔去調用底層驅動去操做修改數據庫。

session.commit(); 
        
MybatisJDBCUtil.closeSession();

沒有返回值得纔有上面這兩條語句,也就是說執行了這兩條語句纔會真正執行插入到數據庫,對數據庫的數據進行修改。

相反,有返回值的就沒有執行這兩條語句,因此只是在本身構造的session中執行了添加語句,可是並無提交到數據庫中,故數據庫中是沒有任何記錄的。

這也就解釋了爲何Mybatis 中修改添加方法爲有返回值後,雖然提示插入數據庫成功,可是當你打開數據庫看不到插入的數據。

Mybatis中插入語句方法種不要有返回值,像這樣寫是正確的。

    @Override
    public void insertProduct(ProductBean productBean) {
        // TODO Auto-generated method stub
        SqlSession session = MybatisJDBCUtil.currentSession();

        ProductIDao productIDao = session.getMapper(ProductIDao.class);// 這裏*.class
                                                                      // 必須對應DAO的接口層
        productIDao.insertProduct(productBean);
        
session.commit(); MybatisJDBCUtil.closeSession(); }

參考資料一:https://my.oschina.net/crazybird/blog/379635?p=1
參考資料二:http://blog.csdn.net/jbgtwang/article/details/7307687
參考資料三:http://blog.csdn.net/after_you/article/details/53844908
相關文章
相關標籤/搜索