詳解Java MyBatis 插入數(shù)據(jù)庫返回主鍵
最近在搞一個(gè)電商系統(tǒng)中由于業(yè)務(wù)需求,需要在插入一條產(chǎn)品信息后返回產(chǎn)品Id,剛開始遇到一些坑,這里做下筆記,以防今后忘記。
類似下面這段代碼一樣獲取插入后的主鍵
User user = new User(); user.setUserName("chenzhou"); user.setPassword("xxxx"); user.setComment("測試插入數(shù)據(jù)返回主鍵功能"); System.out.println("插入前主鍵為:"+user.getUserId()); userDao.insertAndGetId(user);//插入操作 System.out.println("插入后主鍵為:"+user.getUserId());
經(jīng)過查詢網(wǎng)上資料,發(fā)現(xiàn)大致有兩種方式。
方式一:
在實(shí)體類的映射文件 "*Mapper.xml" 這樣寫:
<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" 表示給主鍵設(shè)置自增長
keyProperty="userId" 表示將自增長后的Id賦值給實(shí)體類中的userId字段。
parameterType="com.chenzhou.mybatis.User" 這個(gè)屬性指向傳遞的參數(shù)實(shí)體類
這里提醒下,<insert></insert> 中沒有resultType屬性,不要亂加。
實(shí)體類中uerId 要有g(shù)etter() and setter(); 方法
由于我在MySQL數(shù)據(jù)庫中建表時(shí)候已經(jīng)設(shè)置了字段自增長,故最終我選擇了第二種方式。
第二種方式:
同樣在實(shí)體類的映射文件 "*Mapper.xml" 但是要這樣寫:
<!-- 插入一個(gè)商品 --> <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> 標(biāo)簽是有的。
order="AFTER" 表示先執(zhí)行插入語句,之后再執(zhí)行查詢語句。
可被設(shè)置為 BEFORE 或 AFTER。
如果設(shè)置為 BEFORE,那么它會首先選擇主鍵,設(shè)置 keyProperty 然后執(zhí)行插入語句。
如果設(shè)置為 AFTER,那么先執(zhí)行插入語句,然后是 selectKey 元素-這和如 Oracle 數(shù)據(jù)庫相似,可以在插入語句中嵌入序列調(diào)用
keyProperty="userId" 表示將自增長后的Id賦值給實(shí)體類中的userId字段。
SELECT LAST_INSERT_ID() 表示MySQL語法中查詢出剛剛插入的記錄自增長Id.
實(shí)體類中uerId 要有g(shù)etter() and setter(); 方法
實(shí)現(xiàn)需求,上面那些就足夠了。
這里如果有興趣的,請繼續(xù)聽我講一個(gè)Mybatis中可能誤入的坑。
為什么Mybatis 中修改添加方法為有返回值后,雖然提示插入數(shù)據(jù)庫成功并且也能讀取插入的數(shù)據(jù),但是當(dāng)你打開數(shù)據(jù)庫后就是看不到插入的數(shù)據(jù)?
如果在實(shí)現(xiàn)上述需求時(shí),想插入后返回主鍵的話,切記不要這樣寫。
@Override public Long insertProduct(ProductBean productBean) { // TODO Auto-generated method stub SqlSession session = MybatisJDBCUtil.currentSession(); ProductIDao productIDao = session.getMapper(ProductIDao.class);// 這里*.class // 必須對應(yīng)DAO的接口層 return productIDao.insertProduct(productBean); }
Why?
因?yàn)槿绻闶窍裆厦孢@樣寫,那么執(zhí)行后返回的也不是你想要的主鍵Id,而是執(zhí)行數(shù)據(jù)庫語句后受影響的行數(shù)。
而且,當(dāng)你執(zhí)行后你會發(fā)現(xiàn)提示插入成功,你用代碼也可以讀取出插入的數(shù)據(jù),但是永遠(yuǎn)只有一條記錄。
并且,你打開數(shù)據(jù)庫會發(fā)現(xiàn),數(shù)據(jù)庫中沒有插入成功任何數(shù)據(jù)。
我在這里郁悶了N久,終于發(fā)現(xiàn)了關(guān)鍵所在。
有返回值和沒返回值的區(qū)別在于:
有返回值的只是對數(shù)據(jù)庫只讀模式訪問數(shù)據(jù)庫,對數(shù)據(jù)庫數(shù)據(jù)不會有任何修改,比如各種方式的查詢。
無返回值的則會以讀寫模式訪問數(shù)據(jù)庫,會對數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行修改,比如刪除,增加。
除此之外,根據(jù)個(gè)人理解應(yīng)該mybatis在執(zhí)行插入語句時(shí)會先緩存到構(gòu)造的一個(gè)類似session集合中,然后才去調(diào)用底層驅(qū)動(dòng)去操作修改數(shù)據(jù)庫。
session.commit(); MybatisJDBCUtil.closeSession();
沒有返回值得才有上面這兩條語句,也就是說執(zhí)行了這兩條語句才會真正執(zhí)行插入到數(shù)據(jù)庫,對數(shù)據(jù)庫的數(shù)據(jù)進(jìn)行修改。
相反,有返回值的就沒有執(zhí)行這兩條語句,所以只是在自己構(gòu)造的session中執(zhí)行了添加語句,但是并沒有提交到數(shù)據(jù)庫中,故數(shù)據(jù)庫中是沒有任何記錄的。
這也就解釋了為什么Mybatis 中修改添加方法為有返回值后,雖然提示插入數(shù)據(jù)庫成功,但是當(dāng)你打開數(shù)據(jù)庫看不到插入的數(shù)據(jù)。
Mybatis中插入語句方法種不要有返回值,像這樣寫是正確的。
@Override public void insertProduct(ProductBean productBean) { // TODO Auto-generated method stub SqlSession session = MybatisJDBCUtil.currentSession(); ProductIDao productIDao = session.getMapper(ProductIDao.class);// 這里*.class // 必須對應(yīng)DAO的接口層 productIDao.insertProduct(productBean); session.commit(); MybatisJDBCUtil.closeSession(); }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解讀java?try?catch?異常后還會繼續(xù)執(zhí)行嗎
這篇文章主要介紹了解讀java?try?catch?異常后還會不會繼續(xù)執(zhí)行問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11Idea2020 無法share項(xiàng)目到svn的解決方法
這篇文章主要介紹了Idea2020 無法share項(xiàng)目到svn的解決方法,需要的朋友可以參考下2020-09-09Java 中的CharArrayReader 介紹_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
CharArrayReader 是字符數(shù)組輸入流。它和ByteArrayInputStream類似,只不過ByteArrayInputStream是字節(jié)數(shù)組輸入流,而CharArray是字符數(shù)組輸入流。CharArrayReader 是用于讀取字符數(shù)組,它繼承于Reader2017-05-05