当前位置: 首页 > news >正文

MyBatis中表和实体类的映射

MyBatis 表 ↔ 实体类映射

数据库表字段(下划线user_name),Java 实体属性(驼峰userName)。

两种方案:自动映射手动 resultMap 映射

表:t_user

| id | user_name | user_age | dept_id |

|----|-----------|----------|---------|

| 1 | 张三 | 22 | 1001 |

实体 User.java

public class User { private Long id; private String userName; private Integer userAge; private Long deptId; // getter setter }

一、自动映射(resultType)

MyBatis 自动映射规则:列名和实体属性完全一样就自动赋值

情况 1:数据库下划线,实体驼峰(最常见业务场景)

开启全局配置:下划线转驼峰,不需要写任何映射,直接用resultType

yml 配置

mybatis: configuration: map-underscore-to-camel-case: true
  • 数据库列user_name→ Java 属性userName
  • 数据库列user_age→ Java 属性userAge

mapper xml

<select id="selectAll" resultType="com.entity.User"> select id,user_name,user_age,dept_id from t_user </select>

✅ 查询结果自动封装 User 对象。

⚠️注意:这个配置只作用于resultType,同样也对resultMap生效。

情况 2:字段名字完全一致(不推荐数据库这样设计)

数据库列userName,实体属性userName,不需要开启配置,直接自动映射。

自动映射失效场景

  1. 没有开启下划线转驼峰,数据库下划线,实体驼峰 → 属性为 null
  2. sql 查询的列名和实体属性名完全不匹配
  3. 多表关联查询、嵌套对象、一对一 / 一对多,自动映射搞不定,必须resultMap

二、手动映射 resultMap(核心重点)

适用场景:

  1. 数据库列名和实体属性差异很大
  2. 一对一、一对多关联查询
  3. 需要指定主键、typeHandler 自定义类型处理
  4. 不想开启全局下划线转驼峰配置

基础语法

<!-- type:实体全类名 / 别名;id:resultMap唯一标识 --> <resultMap id="userResultMap" type="com.entity.User"> <!-- <id> 映射主键字段,提升MyBatis解析性能,主键一定要写 --> <id column="id" property="id"/> <!-- column:sql查询出来的列名;property:实体类属性名 --> <result column="user_name" property="userName"/> <result column="user_age" property="userAge"/> <result column="dept_id" property="deptId"/> </resultMap> <!-- 使用resultMap,不要写resultType --> <select id="selectUser" resultMap="userResultMap"> select id,user_name,user_age,dept_id from t_user where id=#{id} </select>

关键点:columnSQL 查询返回的列名,不是原始表字段名! 如果写了别名select user_name as uname,那 column 就要写uname

别名示例

<select id="selectUser" resultMap="userResultMap"> select id,user_name as uname from t_user </select> <resultMap id="userResultMap" type="User"> <id column="id" property="id"/> <result column="uname" property="userName"/> </resultMap>

三、一对一关联映射(association)

User 里面包含 Dept 对象

public class User { private Long id; private String userName; private Dept dept; // 一对一 } public class Dept { private Long deptId; private String deptName; }

方式 1:联合查询,一次 SQL(业务常用)

<resultMap id="userDeptMap" type="User"> <id column="u_id" property="id"/> <result column="user_name" property="userName"/> <!-- association:一对一对象映射 property=实体属性名 javaType=对象类型 --> <association property="dept" javaType="Dept"> <id column="d_id" property="deptId"/> <result column="dept_name" property="deptName"/> </association> </resultMap> <select id="getUser" resultMap="userDeptMap"> select u.id u_id, u.user_name, d.id d_id, d.dept_name from t_user u left join t_dept d on u.dept_id = d.id where u.id=#{id} </select>

方式 2:嵌套查询(多 SQL,会产生 N+1 问题)

<resultMap id="userDeptMap" type="User"> <id column="id" property="id"/> <result column="user_name" property="userName"/> <!-- select:调用另外一个mapper方法;column:传给子查询的参数 --> <association property="dept" javaType="Dept" select="com.mapper.DeptMapper.selectById" column="dept_id"/> </resultMap>

注意 N+1 问题:查询 N 条用户,会额外发起 N 次查询部门,大数据量禁止。

四、一对多关联映射(collection)

一个用户多个订单,User 中存放 List<Order> orderList

public class User { private Long id; private String userName; private List<Order> orderList; //一对多 } public class Order{ private Long orderId; private String orderNo; }
<resultMap id="userOrderMap" type="User"> <id column="u_id" property="id"/> <result column="user_name" property="userName"/> <!-- collection:集合映射,ofType集合里面元素类型 --> <collection property="orderList" ofType="Order"> <id column="o_id" property="orderId"/> <result column="order_no" property="orderNo"/> </collection> </resultMap> <select id="getUserOrder" resultMap="userOrderMap"> select u.id u_id, u.user_name, o.id o_id, o.order_no from t_user u left join t_order o on u.id = o.user_id where u.id=#{id} </select>

ofType:集合泛型里面的实体类型,不是写 List。

五、resultMap 复用:extends 继承

<!--基础resultMap --> <resultMap id="baseUserMap" type="User"> <id column="id" property="id"/> <result column="user_name" property="userName"/> </resultMap> <!--继承上面,追加字段,不用重复写 --> <resultMap id="userWithDeptMap" extends="baseUserMap" type="User"> <association property="dept" javaType="Dept"> <id column="d_id" property="deptId"/> </association> </resultMap>

六、常见坑

  1. resultTyperesultMap二选一,不能同时写
  2. column是查询出来的列名,不是表原始字段,注意 sql 别名
  3. 下划线转驼峰只对 resultType 生效,resultMap 不受影响,resultMap 需要手动写 column-property
  4. <association>javaType<collection>ofType,不要搞混
  5. 嵌套子查询容易 N+1,生产尽量用left join 单 sql
  6. 实体属性大小写严格区分,property 必须和实体 getter/setter 对应
  7. 主键尽量写<id/>标签,MyBatis 内部缓存、去重依赖主键,不写会出现重复对象

自动映射 vs resultMap 选型

表格

方案适用场景
resultType + 下划线驼峰配置单表简单查询,字段一一对应
resultMap字段名差异、一对一、一对多、复杂关联查询

补充:MyBatis‑Plus 封装了实体注解@TableName@TableField,底层也是生成 mybatis 的映射逻辑。

http://www.cnnetsun.cn/news/4335398.html

相关文章:

  • 网易Android校招笔试题解析:从Handler到Binder的核心考点
  • FPGA双游戏系统设计实战:VGA显示与碰撞检测的Verilog实现
  • 网易有道校招笔试题解析:算法、系统设计与备考策略
  • 基于EDS安检X光数据集的目标检测实战:从数据解析到YOLOv8模型部署
  • iPad零电脑零越狱运行MC Java版:Fabric与Iris完整接入指南
  • AI代理0Day漏洞入侵实战复盘:沙箱逃逸与奖励黑客防御方案
  • 基于YOLOV5的细胞检测:医疗AI目标检测模型训练全流程
  • 大数据实训项目全链路实战:从Flume采集到Spark分析再到可视化展示
  • 开源工具选型指南:免费资源、AI编程与项目管理实战
  • 全新16合一美团代付系统源码
  • 2026论文神级降AIGC软件大曝光:一键改写直达人工原创!
  • Android禁用OTA更新指南:ADB脚本清除系统更新弹窗与红点
  • 我的世界AI建筑生成模组:从安装部署到批量生成实践指南
  • 2026实测报告:毕业论文AI论文软件横向测评,千笔AI凭三大硬指标登顶
  • C++实现B站直播场控机器人:从弹幕协议到可编程架构全解析
  • 网易2018校招C++开发笔试题全解析:核心考点、编程题与避坑指南
  • STM32F407气压计定高四轴实战:从滤波到串级PID完整解析
  • 三参数叠前反演核心逻辑与实操避坑指南
  • 基于Java+SSM的农家乐预约系统设计与实现(源码+文档+部署讲解等)
  • 2024年中国50个生态功能保护区空间数据:三件套格式与GIS应用指南
  • 基于JavaWeb的在线学习系统毕设:源码+数据库+部署全攻略
  • 2026年7月上饶市新房价格深度分析报告
  • 中兴交换机配置总结
  • LangChain1.2学习第三章—— LangSmith、提示词模板、历史对话、消息
  • Harness三道防线:门禁、白名单、循环上限如何堵住线上bug
  • SpringBoot+Vue+微信小程序游戏攻略分享系统毕设开发全攻略
  • 8万字Java八股文开源合集:从HashMap到Kafka的高频考点与面试应用
  • 基于Python和Neo4j构建医疗知识图谱问答系统实践
  • 2018字节跳动算法笔试复盘:高频考点与工程实践避坑指南
  • 嵌入式ROS双系统通信实战:上位机+驱动协同设计与CMake构建