Java?Mybatis使用resultMap時(shí),屬性賦值順序錯(cuò)誤的巨坑
Mybatis使用resultMap屬性賦值順序錯(cuò)誤
今天發(fā)現(xiàn)個(gè)坑,新建的表使用生成工具生成的mapper文件和實(shí)體類后,發(fā)現(xiàn)少了個(gè)字段就又手動(dòng)加了下,結(jié)果發(fā)現(xiàn)一個(gè)問(wèn)題
ids是后加入的字段
@Data @Builder public class QueryRecordPo { ? ? ? ?//若干其他屬性.... ? ? private String outputField; ? ? ?//后加的 ? ? private String ids; ? ? ? //若干其他屬性 ? ? //...? }
resultMap中是這樣寫的
? ? <resultMap id="BaseResultMap" type="...."> ? ? ? ? <id column="id" jdbcType="BIGINT" property="id"/> ? ? ? ? ..若干其他屬性 ? ? ? ? <result column="ids" jdbcType="VARCHAR" property="ids"/> ? ? ? ? <result column="output_field" jdbcType="VARCHAR" property="outputField"/> ? ? ? ? ..若干其他屬性 ? ? </resultMap>
可以發(fā)現(xiàn)ids加的位置是不一樣的,實(shí)體類中在outputField屬性下面,但resultMap中在其上面。然后測(cè)試數(shù)據(jù)中ids字段為null,查詢出來(lái)時(shí)卻發(fā)現(xiàn)ids的值和outputField的值是一樣的。但如果ids的字段有值,就可以正確賦值。
mybatis在生成目標(biāo)類進(jìn)行映射時(shí),會(huì)先檢查構(gòu)造函數(shù)聲明情況,但 如果Data注解和Builder注解一塊使用的話就只會(huì)生成全屬性參數(shù)構(gòu)造函數(shù),不會(huì)有默認(rèn)無(wú)參構(gòu)造函數(shù)。全屬性構(gòu)造函數(shù)的參數(shù)順序是和類中屬性聲明順序一致的
在把數(shù)據(jù)庫(kù)字段映射到實(shí)體類的時(shí)候發(fā)現(xiàn)實(shí)體類沒(méi)有默認(rèn)無(wú)參構(gòu)造函數(shù),就會(huì)把數(shù)據(jù)庫(kù)中的字段按照全屬性構(gòu)造函數(shù)參數(shù)的順序依次賦值給實(shí)體類的屬性。但如果實(shí)體類的屬性定義順序與數(shù)據(jù)庫(kù)中字段順序不一致,就會(huì)出現(xiàn)賦值錯(cuò)誤的情況。
然后再為outputField字段賦值時(shí)調(diào)用了set方法 這樣就出現(xiàn)了兩個(gè)不同名但同值的屬性。
解決辦法
1 修改屬性順序保持一致
2 為實(shí)體類加上@NoArgsConstructor和 @AllArgsConstructor注解 使其可以生成無(wú)參數(shù)構(gòu)造函數(shù)即可
之前生成時(shí) 順序都保持了一致,還真沒(méi)發(fā)現(xiàn)這個(gè)問(wèn)題
Mybatis使用resultMap時(shí)需注意
<resultMap id="baseMap" type="com.ei.medical.modules.model.EduEducationKnowledge"> <id column="id" property="id"/> <result column="visitNumber" property="visitNumber"/> <result column="patientName" property="patientName"/> <result column="sendTime" property="sendTime"/> <result column="wardCode" property="wardCode"/> <result column="wardName" property="wardName"/> <result column="categoryCode" property="categoryCode"/> <result column="title" property="title"/> <result column="content" property="content"/> <result column="cover" property="cover"/> </resultMap> <select id="getAllBy" resultMap="baseMap"> SELECT eer.visit_number as visitNumber, eer.patient_name as patientName, eer.send_time as sendTime, eek.id as id, eek.ward_code as wardCode, eek.ward_name as wardName, eek.category_code as categoryCode, eek.title as title, eek.content as content, eek.cover as cover FROM edu_education_record AS eer, edu_education_knowledge AS eek WHERE eer.education_knowledge_id=eek.id </select>
如果是實(shí)體中是直接引用別的對(duì)象的具體參數(shù)字段,直接用原始方式就行
如果是實(shí)體中是list集合
<resultMap id="baseMap" type="com.ei.medical.modules.model.EduEducationKnowledge"> <id column="id" property="id"/> <result column="visitNumber" property="visitNumber"/> <result column="patientName" property="patientName"/> <result column="sendTime" property="sendTime"/> <result column="wardCode" property="wardCode"/> <result column="wardName" property="wardName"/> <result column="categoryCode" property="categoryCode"/> <result column="title" property="title"/> <result column="content" property="content"/> <result column="cover" property="cover"/> <collection property="pic" ofType="string"> <result column="pic"/> </collection> </resultMap> <select id="getAllBy" resultMap="baseMap"> SELECT eer.visit_number as visitNumber, eer.patient_name as patientName, eer.send_time as sendTime, eek.id as id, eek.ward_code as wardCode, eek.ward_name as wardName, eek.category_code as categoryCode, eek.title as title, eek.content as content, eek.cover as cover FROM edu_education_record AS eer, edu_education_knowledge AS eek WHERE eer.education_knowledge_id=eek.id </select>
如果實(shí)體中引用的是別的對(duì)象,可以使用association 標(biāo)簽來(lái)寫
<resultMap id="baseMap" type="com.ei.medical.modules.model.EduEducationKnowledge"> <id column="id" property="id"/> <result column="wardCode" property="wardCode"/> <result column="wardName" property="wardName"/> <result column="categoryCode" property="categoryCode"/> <result column="title" property="title"/> <result column="content" property="content"/> <result column="cover" property="cover"/> <association property="eduEducationRecord" javaType="com.ei.medical.modules.model.EduEducationRecord"> <result column="visitNumber" property="visitNumber"/> <result column="patientName" property="patientName"/> <result column="sendTime" property="sendTime"/> </association> </resultMap> <select id="getAllBy" resultMap="baseMap"> SELECT eer.visit_number as visitNumber, eer.patient_name as patientName, eer.send_time as sendTime, eek.id as id, eek.ward_code as wardCode, eek.ward_name as wardName, eek.category_code as categoryCode, eek.title as title, eek.content as content, eek.cover as cover FROM edu_education_record AS eer, edu_education_knowledge AS eek WHERE eer.education_knowledge_id=eek.id </select>
如果實(shí)體中是引用的別的對(duì)象的list集合,應(yīng)該使用collection 標(biāo)簽
<resultMap id="baseMap" type="com.ei.medical.modules.model.EduEducationKnowledge"> <id column="id" property="id"/> <result column="wardCode" property="wardCode"/> <result column="wardName" property="wardName"/> <result column="categoryCode" property="categoryCode"/> <result column="title" property="title"/> <result column="content" property="content"/> <result column="cover" property="cover"/> <collection property="eduEducationRecordList" ofType="com.ei.medical.modules.model.EduEducationRecord"> <result column="visitNumber" property="visitNumber"/> <result column="patientName" property="patientName"/> <result column="sendTime" property="sendTime"/> </collection> </resultMap> <select id="getAllBy" resultMap="baseMap"> SELECT eer.visit_number as visitNumber, eer.patient_name as patientName, eer.send_time as sendTime, eek.id as id, eek.ward_code as wardCode, eek.ward_name as wardName, eek.category_code as categoryCode, eek.title as title, eek.content as content, eek.cover as cover FROM edu_education_record AS eer, edu_education_knowledge AS eek WHERE eer.education_knowledge_id=eek.id </select>
tips:
使用resultMap的時(shí)候,應(yīng)該直接用as后面的字段名,即自己命的名字
如果沒(méi)有使用as的話,直接使用數(shù)據(jù)庫(kù)中原本的名字
resultMap中各個(gè)標(biāo)簽的含義
tips:
在一個(gè) resultMap 元素中,這些子元素出現(xiàn)的先后順序是有嚴(yán)格規(guī)定的,它們從前到后依次是:constructor–>id --> result–> association–>collection -->discriminator, 不然就會(huì)報(bào)錯(cuò)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
最簡(jiǎn)單的spring boot打包docker鏡像的實(shí)現(xiàn)
這篇文章主要介紹了最簡(jiǎn)單的spring boot打包docker鏡像的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10Java 本地方法Native Method詳細(xì)介紹
這篇文章主要介紹了 Java 本地方法Native Method詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-02-02springboot實(shí)現(xiàn)后臺(tái)上傳圖片(工具類)
這篇文章主要為大家詳細(xì)介紹了springboot實(shí)現(xiàn)后臺(tái)上傳圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04InvocationHandler中invoke()方法的調(diào)用問(wèn)題分析
這篇文章主要介紹了InvocationHandler中invoke()方法的調(diào)用問(wèn)題分析,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11IDEA創(chuàng)建Servlet編寫HelloWorldServlet頁(yè)面詳細(xì)教程(圖文并茂)
在學(xué)習(xí)servlet過(guò)程中參考的教程是用eclipse完成的,而我在練習(xí)的過(guò)程中是使用IDEA的,在創(chuàng)建servlet程序時(shí)遇到了挺多困難,在此記錄一下,這篇文章主要給大家介紹了關(guān)于IDEA創(chuàng)建Servlet編寫HelloWorldServlet頁(yè)面詳細(xì)教程的相關(guān)資料,需要的朋友可以參考下2023-10-10解決MultipartFile.transferTo(dest) 報(bào)FileNotFoundExcep的問(wèn)題
這篇文章主要介紹了解決MultipartFile.transferTo(dest) 報(bào)FileNotFoundExcep的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07Spring Data Jpa 復(fù)合主鍵的實(shí)現(xiàn)
這篇文章主要介紹了Spring Data Jpa 復(fù)合主鍵的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04