1.reusltmap的说明
resultmap定义了数据库的结果映射到java对象的规则,resultmap包含4个属性:
id
: resultmap 的唯一标识type
: 映射到的 java 类型(全限定类名或别名)extends
: 继承另一个 resultmapautomapping
: 是否开启自动映射(true/false)
前三个比较常用
resultmap包含以下子元素,并且子元素是有定义顺序的,如下:
<constructor>
(可选)<id>
(至少一个)<result>
(零个或多个)<association>
(零个或多个)<collection>
(零个或多个)<discriminator>
(可选)
必须遵循上述顺序,如果顺序不正确,mybatis 在解析 xml 时会抛出异常
<id>
元素必须出现在<result>
元素之前- 如果使用
<constructor>
,它必须是第一个元素 <discriminator>
必须是最后一个元素(如果存在)
2.association的使用
<association>
是 mybatis 中用于处理一对一关联关系的元素,它可以将查询结果中的一部分数据映射到一个复杂的关联对象中。
在实际开发中,如果想一次查询两张表的数据,不想通过两次查询的方式,而是想一次查询出来,可以通过两张表关联将表a和表b的数据都查询出来
属性名 | 说明 |
---|---|
property | java对象中的属性名 |
javatype | 关联对象的java类型(全限定类名或别名) |
resultmap | 引用外部定义的resultmap |
column | 传递给嵌套查询的列名(可以是多个列:column="{prop1=col1,prop2=col2}") |
select | 另一个映射语句的id,用于嵌套查询 |
fetchtype | 覆盖全局的延迟加载设置(lazy/eager) |
automapping | 是否启用自动映射(true/false) |
<!-- 一对一关联映射示例 --> <resultmap id="userwithdeptmap" type="com.example.user"> <!-- 用户表字段映射 --> <id column="user_id" property="id" jdbctype="bigint"/> <result column="user_name" property="name" jdbctype="varchar"/> <result column="user_age" property="age" jdbctype="integer"/> <!-- 一对一关联 department 对象 --> <association property="department" javatype="com.example.department"> <id column="dept_id" property="id" jdbctype="bigint"/> <result column="dept_name" property="deptname" jdbctype="varchar"/> <result column="dept_location" property="location" jdbctype="varchar"/> </association> </resultmap>
<select id="selectuserwithdepartment" resultmap="userwithdeptmap"> select u.id as user_id, u.name as user_name, u.age as user_age, d.id as dept_id, d.name as dept_name, d.location as dept_location from user u left join department d on u.dept_id = d.id where u.id = #{userid} </select>
package com.example; public class user { private long id; // 对应 user_id 字段 private string name; // 对应 user_name 字段 private integer age; // 对应 user_age 字段 private department department; // 一对一关联对象 // 必须的 getter 和 setter 方法 public long getid() { return id; } public void setid(long id) { this.id = id; } public string getname() { return name; } public void setname(string name) { this.name = name; } public integer getage() { return age; } public void setage(integer age) { this.age = age; } public department getdepartment() { return department; } public void setdepartment(department department) { this.department = department; } }
package com.example; public class department { private long id; // 对应 dept_id 字段 private string deptname; // 对应 dept_name 字段 private string location; // 对应 dept_location 字段 // 必须的 getter 和 setter 方法 public long getid() { return id; } public void setid(long id) { this.id = id; } public string getdeptname() { return deptname; } public void setdeptname(string deptname) { this.deptname = deptname; } public string getlocation() { return location; } public void setlocation(string location) { this.location = location; } }
使用关联查询只需要指定以下两个属性即可
配置项 | 作用 |
property="department" | 指定 user 类中关联属性的名称(需与字段名一致)。 |
javatype | 指定关联对象的完整类名(可省略,mybatis 通常能自动推断)。 |
3.collection的使用
<collection>
是 mybatis 中用于处理一对多关联关系的核心元素,它能够将查询结果中的多条记录映射到一个集合属性中(如 list、set 等)
属性名 | 是否必填 | 说明 |
---|---|---|
property | 必填 | java对象中的集合属性名称 |
oftype | 条件必填 | 集合中元素的java类型(当不使用resultmap时必填) |
column | 条件必填 | 传递给嵌套查询的列名(使用select时必填) |
select | 可选 | 另一个映射语句的id,用于嵌套查询 |
fetchtype | 可选 | 加载方式(lazy/eager),覆盖全局配置 |
javatype | 可选 | 集合的java类型(如arraylist、hashset等) |
resultmap | 可选 | 引用外部定义的resultmap |
automapping | 可选 | 是否启用自动映射(true/false) |
<resultmap id="userwithordersmap" type="com.example.model.user"> <id property="id" column="user_id"/> <result property="name" column="user_name"/> <result property="age" column="user_age"/> <!-- 一对多关联订单集合 --> <collection property="orders" oftype="com.example.model.order"> <id property="id" column="order_id"/> <result property="orderno" column="order_no"/> <result property="amount" column="order_amount"/> <result property="userid" column="user_id"/> </collection> </resultmap> <select id="selectuserwithorders" resultmap="userwithordersmap"> select u.id as user_id, u.name as user_name, u.age as user_age, o.id as order_id, o.order_no as order_no, o.amount as order_amount, o.user_id from user u left join orders o on u.id = o.user_id where u.id = #{userid} </select>
package com.example.model; import java.util.list; public class user { private long id; private string name; private integer age; private list<order> orders; // 一对多关联的订单集合 // getters and setters public long getid() { return id; } public void setid(long id) { this.id = id; } public string getname() { return name; } public void setname(string name) { this.name = name; } public integer getage() { return age; } public void setage(integer age) { this.age = age; } public list<order> getorders() { return orders; } public void setorders(list<order> orders) { this.orders = orders; } }
package com.example.model; public class order { private long id; private string orderno; private double amount; private long userid; // 外键,关联用户id // getters and setters public long getid() { return id; } public void setid(long id) { this.id = id; } public string getorderno() { return orderno; } public void setorderno(string orderno) { this.orderno = orderno; } public double getamount() { return amount; } public void setamount(double amount) { this.amount = amount; } public long getuserid() { return userid; } public void setuserid(long userid) { this.userid = userid; } }
使用关联查询只需要指定以下两个属性即可
属性名 | 是否必填 | 说明 |
---|---|---|
property | 必填 | java对象中的集合属性名称 |
oftype | 条件必填 | 集合中元素的java类型(当不使用resultmap时必填) |
4.总结
①在 mybatis 的 <resultmap>
中,如果使用 <association>
或 <collection>
映射关联关系,必须为父对象(主对象)至少定义一个 <id>
属性
mybatis 使用 <id>
来唯一标识一个对象,用于:
- 一级/二级缓存的键值
- 解决嵌套映射中的循环引用问题
- 避免重复创建相同对象(性能优化)
关联映射的依赖:
- 当存在
<association>
或<collection>
时,mybatis 需要通过父对象的<id>
来管理关联对象的加载和绑定。
②association及collection中的id属性是可选的,但建议加上,它用于避免重复子对象(例如 join 导致重复数据时去重)。
如果子对象中定义了 <id>
属性,mybatis 会对 <collection>
中的重复子对象进行去重。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论