主题:自定义映射resultMap
"自定义映射resultMap" ,可以解决什么问题:
1-"属性" 和 "字段名" 不一致的情况
2-"多对一" 的情况
3-"一对多" 的情况
一、 若 "字段名" 和 "实体类" 中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)
此时也可通过以下 "两种方式" 处理 "字段名" 和 "实体类" 中的 属性的映射关系
such: "emp_name " 和 "empName" ,这样的情况
方法1: (取别名)
可以通过为字段起别名的方式,保证和实体类中的属性名保持一致。
<select id ="getAllEmp" resultType ="Emp" >
select eid,emp_name empName,age,sex,email from t_emp
</select >
方法2: (配置核心配置文件)
在MyBatis的核心配置文件中的setting标签中,设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰,例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName。
2.1- 核心配置文件
<settings >
<setting name ="mapUnderscoreToCamelCase" value ="true" />
</settings >
//1-已经在"核心配置文件"中配置了<Setting > ,所以可以写 "select * from"
//2-也可以直接使用:resultType="Emp"
<select id ="getAllEmp" resultType ="Emp" >
select * from t_emp
</select >
二、resultMap处理 "字段" 和 "属性 "的映射关系
resultMap:设置自定义映射
属性:
id:表示自定义映射的唯一标识,不能重复
type:查询的数据要映射的实体类的类型
子标签:
id:设置主键的映射关系
result:设置普通字段的映射关系
子标签属性:
property:设置映射关系中实体类中的属性名
column:设置映射关系中表中的字段名
细节:若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射,即使字段名和属性名一致的属性也要映射,也就是全部属性都要列出来
<resultMap id ="empResultMap" type ="Emp" >
<id property ="eid" column ="eid" > </id >
<result property ="empName" column ="emp_name" > </result >
<result property ="age" column ="age" > </result >
<result property ="sex" column ="sex" > </result >
<result property ="email" column ="email" > </result >
</resultMap >
<select id ="getAllEmp" resultMap ="empResultMap" >
select * from t_emp
</select >
三、"多对一" 映射处理:
多对一,对应的是 "对象"
在"多的实体类" 中写"一的对象"
eg:
private Integer eid;
private String empName;
private Integer age;
private String sex;
private String email;
private Dept dept;
1- "级联方式" 处理映射关系
<resultMap id ="empAndDeptResultMapOne" type ="Emp" >
<id property ="eid" column ="eid" > </id >
<result property ="empName" column ="emp_name" > </result >
<result property ="age" column ="age" > </result >
<result property ="sex" column ="sex" > </result >
<result property ="email" column ="email" > </result >
<result property ="dept.did" column ="did" > </result >
<result property ="dept.deptName" column ="dept_name" > </result >
</resultMap >
<select id ="getEmpAndDept" resultMap ="empAndDeptResultMapOne" >
select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
</select >
2-使用 "association" 处理映射关系 (处理 "多对一")
association:处理多对一的映射关系
property:需要处理多对的映射关系的属性名
javaType:该属性的类型
<resultMap id ="empAndDeptResultMapTwo" type ="Emp" >
<id property ="eid" column ="eid" > </id >
<result property ="empName" column ="emp_name" > </result >
<result property ="age" column ="age" > </result >
<result property ="sex" column ="sex" > </result >
<result property ="email" column ="email" > </result >
<association property ="dept" javaType ="Dept" >
<id property ="did" column ="did" > </id >
<result property ="deptName" column ="dept_name" > </result >
</association >
</resultMap >
<select id ="getEmpAndDept" resultMap ="empAndDeptResultMapTwo" >
select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
</select >
3-分步查询:
分布查询的好处:SQL语句可以不写"连接语句",只要写对应的"查询"语句
1. 查询员工信息
select:设置分布查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
column:设置分步查询的条件
"多对一" 第一步:
Emp getEmpAndDeptByStepOne (@Param("eid") Integer eid) ;
<resultMap id ="empAndDeptByStepResultMap" type ="Emp" >
<id property ="eid" column ="eid" > </id >
<result property ="empName" column ="emp_name" > </result >
<result property ="age" column ="age" > </result >
<result property ="sex" column ="sex" > </result >
<result property ="email" column ="email" > </result >
<association property ="dept"
select ="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column ="did" > //是Emp的外键
</association >
</resultMap >
<select id ="getEmpAndDeptByStepOne" resultMap ="empAndDeptByStepResultMap" >
select * from t_emp where eid = #{eid}
</select >
"多对一" 第二步:
Dept getEmpAndDeptByStepTwo (@Param("did") Integer did) ;
<!--此处的resultMap仅是处理字段和属性的映射关系-->
<resultMap id="EmpAndDeptByStepTwoResultMap" type="Dept" >
<id property="did" column="did" ></id>
<result property="deptName" column="dept_name" ></result>
</resultMap>
<!--Dept getEmpAndDeptByStepTwo (@Param("did") Integer did) ;-->
<select id="getEmpAndDeptByStepTwo" resultMap="EmpAndDeptByStepTwoResultMap" >
select * from t_dept where did = #{did}
</select>
解析:逻辑:
三、"一对多" 的映射处理
一对多,对应的是"集合"
public class Dept {
private Integer did;
private String deptName;
private List<Emp> emps;
}
1-collection
collection:用来处理 "一对多" 的映射关系 ---> (collection 用来处理 "集合")
ofType:表示该属性对饮的集合中存储的数据的类型
<resultMap id ="DeptAndEmpResultMap" type ="Dept" >
<id property ="did" column ="did" > </id >
<result property ="deptName" column ="dept_name" > </result >
<collection property ="emps" ofType ="Emp" > //细节:collection和ofType
<id property ="eid" column ="eid" > </id >
<result property ="empName" column ="emp_name" > </result >
<result property ="age" column ="age" > </result >
<result property ="sex" column ="sex" > </result >
<result property ="email" column ="email" > </result >
</collection >
</resultMap >
<select id ="getDeptAndEmp" resultMap ="DeptAndEmpResultMap" >
select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select >
分步查询
Dept getDeptAndEnpByStepOne (@Param("did") Integer did) ;
<resultMap id="DeptAndEmpByStepResultMap" type="Dept" >
<id property="did" column="did" ></id>
<result property="deptName" column="dept_name" ></result>
<collection property="emps"
select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="did" >
</collection>
</resultMap>
<!-- Dept getDeptAndEnpByStepOne (@Param("did") Integer did) ;-->
<select id="getDeptAndEnpByStepOne" resultMap="DeptAndEmpByStepResultMap" >
select * from t_dept where t_dept.did = #{did}
</select>
List <Emp > getDeptAndEmpByStepTwo(@Param ("did" ) Integer did);
<select id ="getDeptAndEmpByStepTwo" resultType ="Emp" >
select * from t_emp where t_emp.did = #{did}
</select >
四、延迟加载:
解析:(在 "分布查询" 的时候会用到 --> "延迟加载")
分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载
此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加载)|eager(立即加载)”
//核心配置文件:
<settings >
<setting name ="lazyLoadingEnabled" value ="true" />
</settings >
关闭延迟加载,两条SQL语句都运行了
开启延迟加载,只运行获取emp的SQL语句
开启后,需要用到查询dept的时候才会调用相应的SQL语句:
fetchType:当开启了全局的延迟加载之后,可以通过该属性手动控制延迟加载的效果,fetchType=“lazy(延迟加载)|eager(立即加载)”
<resultMap id ="empAndDeptByStepResultMap" type ="Emp" >
<id property ="eid" column ="eid" > </id >
<result property ="empName" column ="emp_name" > </result >
<result property ="age" column ="age" > </result >
<result property ="sex" column ="sex" > </result >
<result property ="email" column ="email" > </result >
<association property ="dept"
select ="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column ="did"
fetchType ="lazy" > </association > // fetchType:lazy / eager
</resultMap >
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?