实际开发中有很多多表查询的情况,下面来学习多表查询如何传递参数,如何接收返回结果。
其实参数传递无论是单表还是多表操作都是一样的,可以使用map或者pojo对象传参
但是接收返回结果的方式就不一样了,因为涉及到多张表(不同类类型)的结果,因此多表查询的重点在于如何接收查询结果
- 多表查询封装结果的3种方式
- 使用resultMap绑定表中列和类属性关系,接收多对一的查询结果
- 使用resultMap+嵌套select查询,接收一对多的查询结果
- 使用VO(view Object)对象接收一对多的查询结果
- 多表查询的分类
- 多对一查询 / 一对一
- 一对多查询 / 多对多
8.1. 多对一查询
-
区分多对一关系数据的特点
数据A 有一个 数据B ,多个A可以有同一个B。
-
案例:查询订单时,展示对应的用户信息
- 确定查询需求是否属于多对一
- 准备多对一环境(表、类)
8.1.1. 确定查询需求
确定查询需求是否属于多对一
- 展示订单时,多个订单属于同一个用户
8.1.2. 多对一环境
多个订单对应一个用户,一个用户有多个订单
- Orders.java
public class Orders {
private Long orderId; //订单ID
private Integer userId; //用户ID
private Double orderPrice; //订单金额
private String payment; //支付方式
private String state; //订单状态
private Date orderCreatetime; //下单时间
private String note; //备注
private User user; //一个订单只对应一个用户
//get set ...
}
- User.java
public class User {
private Integer uid; //用户ID
private String username; //用户名
private Date birthday; //生日
private String phone; //手机号
private String sex; //性别
private String address; //地址
//一个用户拥有多个订单
private ArrayList<Orders> orders =new ArrayList<Orders>();
//get set...
}
- 对应orders、user表
CREATE TABLE `orders` (
`order_id` int NOT NULL COMMENT '订单编号',
`user_id` int NOT NULL COMMENT '下单用户id',
`order_price` double NOT NULL COMMENT '订单金额',
`payment` varchar(20) DEFAULT NULL COMMENT '支付方式',
`state` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '订单状态',
`order_createtime` date DEFAULT NULL COMMENT '下单时间',
`note` varchar(100) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`order_id`),
KEY `FK_orders_1` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `orders` */
insert into `orders`(`order_id`,`user_id`,`order_price`,`payment`,`state`,`order_createtime`,`note`) values (10000563,6,100,'会员','已支付','0202-03-21','汽车精洗'),(10000564,8,600,'支付宝','已支付','2020-03-26','土豪客户'),(10000565,6,320,'会员','已支付','2020-03-29','普通保养'),(10000566,10,80,'微信','已退单','2020-03-29','预约洗车,取消订单');
CREATE TABLE `user` (
`uid` int NOT NULL AUTO_INCREMENT,
`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`phone` varchar(15) DEFAULT NULL COMMENT '手机号',
`sex` char(2) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
/*Data for the table `user` */
insert into `user`(`uid`,`username`,`birthday`,`phone`,`sex`,`address`) values (1,'王五','1996-12-25',NULL,NULL,NULL),(2,'小花','1998-06-02','13659596872','2','江苏沭阳'),(6,'张小明','1996-01-06','15263671526','2','江苏南京'),(8,'张三丰','1998-12-25','15966633888','1','北京朝阳'),(10,'张三','1998-10-16','15777778696','1','北京海淀'),(12,'刘皇叔','2000-03-22','17888888888','1','江苏连云港');
8.1.3. 使用resultMap接收
- 编写mapper接口方法
- 编写statement
- 编写resultMap
- 测试
1. mapper接口方法
public interface OrderMapper {
//展示所有订单信息,以及订单所属客户姓名手机号
public List<Orders> listOrderAndUser();
}
2. 编写SQL片段
- 原生SQL
SELECT
o.order_id,
o.user_id,
o.order_price,
o.payment,
o.state,
o.order_createtime,
o.note,
u.uid,
u.username,
u.phone
FROM orders o, `user` u
WHERE o.user_id = u.uid
- 编写statement
<!--多对一查询:多个订单对应一个用户-->
<select id="listOrderAndUser" resultMap="baseResultMap">
SELECT
o.order_id,
o.user_id,
o.order_price,
o.payment,
o.state,
o.order_createtime,
o.note,
u.uid,
u.username,
u.phone
FROM orders o, `user` u
WHERE o.user_id = u.uid
</select>
3. 编写resultMap
编写resultMap封装查询结果
<!-- type: 对应的映射类型 -->
<!--
所有属性都需要和对应的列绑定关系
只有绑定属性和列的关系,才会将查询结果封装到绑定的属性中
因为resultMap是自定义的关系映射,
使用resultMap,mybatis就不会再自动绑定列和属性的关系
-->
<resultMap id="baseResultMap" type="orders">
<id property="orderId" column="order_id"></id>
<result property="userId" column="uid" javaType="int" jdbcType="INTEGER"></result>
<result property="orderPrice" column="order_price"></result>
<result property="payment" column="payment"></result>
<result property="state" column="state"></result>
<result property="orderCreatetime" column="order_createtime"></result>
<result property="note" column="note"></result>
<!--association定义多对一或者一对一的关系-->
<association property="user