mybatis相同的sql查詢第二次查不出結(jié)果問題
相同的sql查詢第二次查不出結(jié)果問題
問題分析
今天在做公司業(yè)務(wù),大致是用戶傳來訂單號(hào)(買卡)和手機(jī)號(hào)對(duì)其進(jìn)行卡綁定,其中如果已經(jīng)操作過則返回操作后的狀態(tài),問題出現(xiàn)在如果是項(xiàng)目啟動(dòng)第一次訪問,會(huì)正常返回結(jié)果,第二次訪問時(shí)會(huì)報(bào)找不到卡信息的錯(cuò)誤,但是代碼是同一個(gè),查詢語句也一樣,為什么會(huì)出現(xiàn)這種情況?找遍百度,未果,自己摸索著尋找問題。
問題探索
首先對(duì)查詢方法進(jìn)行了排除,未果;然后尋找代碼中問題,發(fā)現(xiàn)遍歷卡信息(可找到多張卡)時(shí),對(duì)于已經(jīng)操作過的會(huì)進(jìn)行remove()操作,注釋掉這行,程序有結(jié)果,但是會(huì)重新更新卡信息,不是需要的結(jié)果;最后發(fā)現(xiàn)是對(duì)list進(jìn)行remove()操作時(shí)都會(huì)出錯(cuò),于是聯(lián)想到了MyBatis的緩存。
MyBatis緩存介紹
一級(jí)緩存:即session緩存,作用域?yàn)?Session,當(dāng) Session flush 或 close 之后,該Session中的所有 Cache 就將清空,默認(rèn)開啟。注意:集成spring(使用mybatis-spring)時(shí):
每次查詢spring會(huì)重新創(chuàng)建SqlSession,所以一級(jí)緩存是不生效的;
而當(dāng)開啟事務(wù)時(shí),spring會(huì)使用同一個(gè)SqlSession做查詢,所以這個(gè)情況下一級(jí)緩存是生效的。
二級(jí)緩存:即全局緩存,其作用域?yàn)?Mapper(Namespace),默認(rèn)關(guān)閉。
問題原因
上述提到了MyBatis的緩存機(jī)制,查看項(xiàng)目配置后發(fā)現(xiàn)問題在于第一次查詢到結(jié)果會(huì)放到緩存中,程序?qū)Σ榈降慕Y(jié)果list進(jìn)行了remove操作,所以緩存中的list會(huì)發(fā)生變化,第二次查詢時(shí)會(huì)從緩存中將操作過的list查找出來(mybatis返回的實(shí)體類的內(nèi)存地址是相同的),故而產(chǎn)生了我們不需要的結(jié)果,之前項(xiàng)目中使用的是與Spring集成的,使用的session是SqlSessionTemplate,這里是默認(rèn)關(guān)閉了一級(jí)緩存,而今天項(xiàng)目中沒有與Spring集成,創(chuàng)建session使用的是SqlsessionFactory的openSession()方法,這里查找時(shí)默認(rèn)會(huì)先從緩存中查詢,綜上,第二次我們查到的只是緩存中的數(shù)據(jù)[2]。
解決方案
既然第二次會(huì)從緩存中讀數(shù)據(jù),不可能修改項(xiàng)目配置關(guān)閉一級(jí)緩存,所以可以通過刷新緩存來達(dá)到我們所需要的目的
方案一:通過SqlSessionUtils.getSqlSession(sqlSessionFactory).clearCache()方法刷新緩存
方案二:在mapper.xml對(duì)應(yīng)的查找語句中添加flushCache="true"
<select id="selectCardInfoByOrderId" resultType="xxx" parameterType="java.util.Map" flushCache="true"></select>
mybatis條件查詢?nèi)菀子鲆姷腻e(cuò)誤
在使用mybatis的條件查詢時(shí),
一不小心就容易出現(xiàn)這個(gè)錯(cuò)誤
19-Dec-2017 16:04:38.742 嚴(yán)重 [http-nio-8090-exec-6] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [SpringMVC] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'endoscopeType' in 'class java.lang.String'] with root cause org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'endoscopeType' in 'class java.lang.String'at org.apache.ibatis.reflection.Reflector.getGetInvoker(Reflector.java:380)at org.apache.ibatis.reflection.MetaClass.getGetInvoker(MetaClass.java:170)at org.apache.ibatis.reflection.wrapper.BeanWrapper.getBeanProperty(BeanWrapper.java:152)at org.apache.ibatis.reflection.wrapper.BeanWrapper.get(BeanWrapper.java:48)
這是mapper.xml文件:
<select id="findByEndoscopeType" resultMap="BaseResultMap" parameterType="java.lang.String"> ? ? SELECT * ? ? FROM endoscope ? ? <where> ? ? ? ? <if test="endoscopeType != null"> ? ? ? ? ? ? endoscope_type = #{endoscopeType,jdbcType=VARCHAR} ? ? ? ? </if> ? ? </where> </select>
出錯(cuò)的原因是因?yàn)榧由?<if> 標(biāo)簽時(shí),endoscope屬性沒有包含在String endoscopeType中
兩種解決方法
1.將<if>標(biāo)簽去掉;
2.傳入?yún)?shù)放在對(duì)象中傳進(jìn)來;
<select id="findByEndoscopeType" resultMap="BaseResultMap" parameterType="com.iel.endoscope.entity.Endoscope"> ? ? SELECT * ? ? FROM endoscope ? ? <where> ? ? ? ? <if test="endoscopeType != null"> ? ? ? ? ? ? endoscope_type = #{endoscopeType,jdbcType=VARCHAR} ? ? ? ? </if> ? ? </where> </select>
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java Metrics系統(tǒng)性能監(jiān)控工具的使用詳解
Metrics是一個(gè)Java庫,可以對(duì)系統(tǒng)進(jìn)行監(jiān)控,統(tǒng)計(jì)一些系統(tǒng)的性能指標(biāo)。本文就來和大家詳細(xì)聊聊這個(gè)工具的具體使用,希望對(duì)大家有所幫助2022-11-11java高并發(fā)ScheduledThreadPoolExecutor與Timer區(qū)別
這篇文章主要為大家介紹了java高并發(fā)ScheduledThreadPoolExecutor與Timer區(qū)別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Geotools實(shí)現(xiàn)shape文件的寫入功能
Geotools作為開源的Java?GIS三方庫,已經(jīng)成為GIS服務(wù)器端的主流開源庫,其功能非常強(qiáng)大,涉及到GIS業(yè)務(wù)的方方面面,其中就包括GIS數(shù)據(jù)的讀寫,今天小編就借助Geotools來實(shí)現(xiàn)shape數(shù)據(jù)的寫入,需要的朋友可以參考下2023-08-08解決springboot使用logback日志出現(xiàn)LOG_PATH_IS_UNDEFINED文件夾的問題
這篇文章主要介紹了解決springboot使用logback日志出現(xiàn)LOG_PATH_IS_UNDEFINED文件夾的問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04RabbitMQ消息隊(duì)列的目錄結(jié)構(gòu)
這篇文章主要介紹了RabbitMQ消息隊(duì)列的目錄結(jié)構(gòu),RabbitMQ?屬于消息中間件,主要用于組件之間的解耦,消息的發(fā)送者無需知道消息使用者的存在,反之亦然,那么用了那么久RabbitMQ,其目錄結(jié)構(gòu)是怎樣的呢,讓我們一起來看一下吧2023-08-08Java實(shí)現(xiàn)數(shù)獨(dú)小游戲
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)數(shù)獨(dú)小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05