Java Mybatis使用resultMap时,属性赋值顺序错误的巨坑

 更新时间:2022年01月20日 09:49:25   作者:百事可乐_  
这篇文章主要介绍了Java Mybatis使用resultMap时,属性赋值顺序错误的巨坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Mybatis使用resultMap属性赋值顺序错误

今天发现个坑,新建的表使用生成工具生成的mapper文件和实体类后,发现少了个字段就又手动加了下,结果发现一个问题

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>

可以发现ids加的位置是不一样的,实体类中在outputField属性下面,但resultMap中在其上面。然后测试数据中ids字段为null,查询出来时却发现ids的值和outputField的值是一样的。但如果ids的字段有值,就可以正确赋值。

mybatis在生成目标类进行映射时,会先检查构造函数声明情况,但 如果Data注解和Builder注解一块使用的话就只会生成全属性参数构造函数,不会有默认无参构造函数。全属性构造函数的参数顺序是和类中属性声明顺序一致的

在把数据库字段映射到实体类的时候发现实体类没有默认无参构造函数,就会把数据库中的字段按照全属性构造函数参数的顺序依次赋值给实体类的属性。但如果实体类的属性定义顺序与数据库中字段顺序不一致,就会出现赋值错误的情况。

然后再为outputField字段赋值时调用了set方法 这样就出现了两个不同名但同值的属性。

解决办法

1 修改属性顺序保持一致

2 为实体类加上@NoArgsConstructor和 @AllArgsConstructor注解 使其可以生成无参数构造函数即可

之前生成时 顺序都保持了一致,还真没发现这个问题

Mybatis使用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打包docker镜像的实现

    最简单的spring boot打包docker镜像的实现

    这篇文章主要介绍了最简单的spring boot打包docker镜像的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Java 本地方法Native Method详细介绍

    Java 本地方法Native Method详细介绍

    这篇文章主要介绍了 Java 本地方法Native Method详细介绍的相关资料,需要的朋友可以参考下
    2017-02-02
  • springboot实现后台上传图片(工具类)

    springboot实现后台上传图片(工具类)

    这篇文章主要为大家详细介绍了springboot实现后台上传图片,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • Java中断一个线程操作示例

    Java中断一个线程操作示例

    这篇文章主要介绍了Java中断一个线程操作,结合实例形式分析了java中断线程相关的interrupt()、isInterrupted()及interrupted()函数使用技巧,需要的朋友可以参考下
    2019-10-10
  • InvocationHandler中invoke()方法的调用问题分析

    InvocationHandler中invoke()方法的调用问题分析

    这篇文章主要介绍了InvocationHandler中invoke()方法的调用问题分析,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • IDEA创建Servlet编写HelloWorldServlet页面详细教程(图文并茂)

    IDEA创建Servlet编写HelloWorldServlet页面详细教程(图文并茂)

    在学习servlet过程中参考的教程是用eclipse完成的,而我在练习的过程中是使用IDEA的,在创建servlet程序时遇到了挺多困难,在此记录一下,这篇文章主要给大家介绍了关于IDEA创建Servlet编写HelloWorldServlet页面详细教程的相关资料,需要的朋友可以参考下
    2023-10-10
  • 解决MultipartFile.transferTo(dest) 报FileNotFoundExcep的问题

    解决MultipartFile.transferTo(dest) 报FileNotFoundExcep的问题

    这篇文章主要介绍了解决MultipartFile.transferTo(dest) 报FileNotFoundExcep的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java C++题解eetcode940不同的子序列 II

    Java C++题解eetcode940不同的子序列 II

    这篇文章主要为大家介绍了Java C++题解eetcode940不同的子序列 II实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • Spring Data Jpa 复合主键的实现

    Spring Data Jpa 复合主键的实现

    这篇文章主要介绍了Spring Data Jpa 复合主键的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • Window搭建部署RocketMQ步骤详解

    Window搭建部署RocketMQ步骤详解

    这篇文章主要介绍了Window搭建部署RocketMQ步骤详解,RocketMq是一个由阿里巴巴开源的消息中间件,脱胎去阿里每部使用的MetaQ,在设计上借鉴了Kafka。,需要的朋友可以参考下
    2019-06-06

最新评论