mybatis resultmap 如何为对象赋值的调用顺序
resultmap 为对象赋值的调用顺序
写了一个mybatis的mapper映射文件,
java bean定义如下
public class GroupCourseResult extends GroupResult { private String cid; private String cname; public GroupCourseResult(int stuschool, int nian, String stuclass, String cid, String cname) { super(stuschool, nian, stuclass); this.cid = cid; this.cname = cname; } public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } }
部分mybatis映射文件如下
<select id="selectFailedCourseRationByGroupIdAndCourseName" resultType="GroupCourseResult"> ... </select>
实体类中的属性名和查询的列名完全匹配,但是没有查询stuclass,则封装后的实体类中的stuclass属性应该为空。
然而程序运行后,stuclass属性不仅不为空,还与cname完全相同,百思不得其解,故翻了翻mybatis的源码。
在mybatis中的DefaultResultSetHandler类中,
createResultObject方法的代码如下
private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix) throws SQLException { final Class<?> resultType = resultMap.getType(); final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory); final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings(); if (hasTypeHandlerForResultObject(rsw, resultType)) { return createPrimitiveResultObject(rsw, resultMap, columnPrefix); } else if (!constructorMappings.isEmpty()) { return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix); } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) { return objectFactory.create(resultType); } else if (shouldApplyAutomaticMappings(resultMap, false)) { return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs); } throw new ExecutorException("Do not know how to create an instance of " + resultType); }
经过调试发现,mybatis会先查找该javabean有无默认构造方法,如果有则采用设值注入,若没有,则根据javabean的有参构造方法进行设值,而在8以前的jdk版本中,我们利用反射只能获取到参数类型,不能获取到参数名称,这其中设值可能出现了匹配失误,将cname的值同时赋给了cname和stuclass。
想要解决这个问题,只须在javabean中添加默认构造方法即可。
使用resultMap时需注意的问题
如果是实体中是直接引用别的对象的具体参数字段,
直接用原始方式就行
<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>
如果是实体中是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>
如果实体中引用的是别的对象,
使用association 标签来写
<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>
如果实体中是引用的别的对象的list集合,
应该使用collection标签
<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的时候,应该直接用as后面的字段名,即自己命的名字
如果没有使用as的话,直接使用数据库中原本的名字
resultMap中各个标签的含义
tips:
在一个 resultMap 元素中,这些子元素出现的先后顺序是有严格规定的,它们从前到后依次是:constructor–>id --> result–> association–>collection -->discriminator, 不然就会报错。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
利用Spring boot+LogBack+MDC实现链路追踪
这篇文章主要介绍了利用Spring boot+LogBack+MDC实现链路追踪,MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对,下文详细介绍需要的小伙伴可以参考一下2022-04-04Java abstract class 与 interface对比
这篇文章主要介绍了 Java abstract class 与 interface对比的相关资料,需要的朋友可以参考下2016-12-12
最新评论