Mybatis高级映射多对多查询
2020-7-21 杨静
Mybatis高级映射多对多查询','紧接着上一篇文章:Mybatis高级映射一对多查询 写
一、开发准备
1、新建数据表(四张表)和添加测试数据
- DROP TABLE IF EXISTS `items`;
- DROP TABLE IF EXISTS `orders`;
- DROP TABLE IF EXISTS `user`;
- DROP TABLE IF EXISTS `orderdetail`;
- /*items是商品表*/
- CREATE TABLE `items` (
- `id` INT(11) NOT NULL AUTO_INCREMENT,
- `name` VARCHAR(32) NOT NULL COMMENT \'商品名称\',
- `price` FLOAT(10,1) NOT NULL COMMENT \'商品定价\',
- `detail` TEXT COMMENT \'商品描述\',
- `pic` VARCHAR(64) DEFAULT NULL COMMENT \'商品图片\',
- `createtime` DATETIME NOT NULL COMMENT \'生产日期\',
- PRIMARY KEY (`id`)
- ) ENGINE=INNODB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
- /*user是用户表*/
- CREATE TABLE `user` (
- `id` INT(11) NOT NULL AUTO_INCREMENT,
- `username` VARCHAR(32) NOT NULL COMMENT \'用户名称\',
- `birthday` DATE DEFAULT NULL COMMENT \'生日\',
- `gender` CHAR(1) DEFAULT NULL COMMENT \'性别\',
- `address` VARCHAR(256) DEFAULT NULL COMMENT \'地址\',
- PRIMARY KEY (`id`)
- ) ENGINE=INNODB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
- /*orders是订单表*/
- CREATE TABLE `orders` (
- `id` INT(11) NOT NULL AUTO_INCREMENT,
- `user_id` INT(11) NOT NULL COMMENT \'下单用户id\',
- `number` VARCHAR(32) NOT NULL COMMENT \'订单号\',
- `createtime` DATETIME NOT NULL COMMENT \'创建订单时间\',
- `note` VARCHAR(100) DEFAULT NULL COMMENT \'备注\',
- PRIMARY KEY (`id`),
- KEY `FK_orders_1` (`user_id`),
- CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
- ) ENGINE=INNODB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
- /*orderdetail是订单明细表*/
- DROP TABLE IF EXISTS orderdetail;
- CREATE TABLE `orderdetail` (
- `id` INT(11) NOT NULL AUTO_INCREMENT,
- `orders_id` INT(11) NOT NULL COMMENT \'订单id\',
- `items_id` INT(11) NOT NULL COMMENT \'商品id\',
- `items_num` INT(11) DEFAULT NULL COMMENT \'商品购买数量\',
- PRIMARY KEY (`id`),
- KEY `FK_orderdetail_1` (`orders_id`),
- KEY `FK_orderdetail_2` (`items_id`),
- CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
- CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
- ) ENGINE=INNODB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
为了测试,我这里随便填了些数据
2、思路分析
订单项和订单明细是一对多的关系,所以本文主要来查询订单表,然后关联订单明细表,这样就有一对多的问题出来了。
因为多对多比较复杂,总公共有四张表,我们先来分析一下思路:
1、将用户信息映射到User中;
2、在User类中添加订单列表属性
List
,将用户创建的订单映射到ordersList中;ordersList 3、在Orders中添加订单明细列表属性
List
,将订单的明细映射到orderDetails中;orderDetails 4、在OrderDetail中添加Items属性,将订单明细所对应的商品映射到Items中。
经过这样分析后,感觉虽然有点复杂,但是好像不是很难的样子,映射的方法也跟前面的一样,只不过这里表有点多,关系有点复杂。下面来写映射文件:
- <select id=\"findUserAndItemsResultMap\" resultMap=\"UserAndItemsResultMap\">
- SELECT
- orders.*,
- user.`username`,
- user.`sex`,
- user.`address`,
- orderdetail.`id` orderdetail_id,
- orderdetail.`items_id`,
- orderdetail.`items_num`,
- orderdetail.`orders_id`,
- items.`name` items_name,
- items.`detail` items_detail,
- items.`price` items_price
- FROM
- orders,
- USER,
- orderdetail,
- items
- WHERE orders.`user_id`=user.`id` AND orders.`id` = orderdetail.`orders_id` AND orderdetail.`items_id`=items.`id`
- select>
我们先看一下查询结果:
二、代码实现
1、四个持久化类
① User.java
- package com.liuyanzhao.mybatis.po;
- import java.util.Date;
- import java.util.List;
- /**
- * 用户的持久类
- */
- public class User {
- private int id; //编号
- private String username; //用户名
- private String gender; //性别
- private Date birthday; //生日
- private String address; //地址
- public List
getOrdersList() { - return ordersList;
- }
- public void setOrdersList(List
ordersList) { - this.ordersList = ordersList;
- }
- //用户创建的订单列表
- private List
ordersList; - public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getGender() {
- return gender;
- }
- public void setGender(String gender) {
- this.gender = gender;
- }
- public Date getBirthday() {
- return birthday;
- }
- public void setBirthday(Date birthday) {
- this.birthday = birthday;
- }
- public String getAddress() {
- return address;
- }
- public void setAddress(String address) {
- this.address = address;
- }
- }
注意:需要在用户表中加入 订单列表
② Items.java
- package com.liuyanzhao.mybatis.po;
- import java.util.Date;
- /**
- * 商品的持久类
- */
- public class Items {
- private int id;
- private String name;
- private double price;
- private String detail;
- private String pic;
- private Date createTime;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public double getPrice() {
- return price;
- }
- public void setPrice(double price) {
- this.price = price;
- }
- public String getDetail() {
- return detail;
- }
- public void setDetail(String detail) {
- this.detail = detail;
- }
- public String getPic() {
- return pic;
- }
- public void setPic(String pic) {
- this.pic = pic;
- }
- public Date getCreateTime() {
- return createTime;
- }
- public void setCreateTime(Date createTime) {
- this.createTime = createTime;
- }
- }
③ Orders.java
- package com.liuyanzhao.mybatis.po;
- import java.util.Date;
- import java.util.List;
- /**
- * 订单的持久类和扩展类
- */
- public class Orders {
- private int id;
- private int userId;
- private String number;
- private Date createTime;
- private String note;
- //订单明细
- private List
orderdetails; - public List
getOrderdetails() { - return orderdetails;
- }
- public void setOrderdetails(List
orderdetails) { - this.orderdetails = orderdetails;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public int getUserId() {
- return userId;
- }
- public void setUserId(int userId) {
- this.userId = userId;
- }
- public String getNumber() {
- return number;
- }
- public void setNumber(String number) {
- this.number = number;
- }
- public Date getCreateTime() {
- return createTime;
- }
- public void setCreateTime(Date createTime) {
- this.createTime = createTime;
- }
- public String getNote() {
- return note;
- }
- public void setNote(String note) {
- this.note = note;
- }
- }
注意:订单列表中,需要订单的详细信息,不需要用户信息
④ Orderdetail.java
- package com.liuyanzhao.mybatis.po;
- /**
- * 订单明细的持久类
- */
- public class Orderdetail {
- private int id;
- private int ordersId;
- private int itemsId;
- private int itemsNum;
- //明细对应的商品信息
- private Items items;
- public Items getItems() {
- return items;
- }
- public void setItems(Items items) {
- this.items = items;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public int getOrdersId() {
- return ordersId;
- }
- public void setOrdersId(int ordersId) {
- this.ordersId = ordersId;
- }
- public int getItemsId() {
- return itemsId;
- }
- public void setItemsId(int itemsId) {
- this.itemsId = itemsId;
- }
- public int getItemsNum() {
- return itemsNum;
- }
- public void setItemsNum(int itemsNum) {
- this.itemsNum = itemsNum;
- }
- }
注意:订单明细里,需要 商品信息
2、订单代理 即mapper.java
OrdersMapperCustom.java
- package com.liuyanzhao.mybatis.mapper;
- import com.liuyanzhao.mybatis.po.User;
- import java.util.List;
- /**
- * 订单 mapper
- */
- public interface OrdersMapperCustom {
- //查询用户购买的商品信息
- public List
findUserAndItemsResultMap() throws Exception; - }
3、OrdersMapperCustom.xml 映射文件
- xml version=\"1.0\" encoding=\"UTF-8\" ?>
- PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"
- \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">
- <mapper namespace=\"com.liuyanzhao.mybatis.mapper.OrdersMapperCustom\">
- <resultMap id=\"UserAndItemsResultMap\" type=\"com.liuyanzhao.mybatis.po.User\">
- <id column=\"user_id\" property=\"id\">id>
- <result column=\"username\" property=\"username\">result>
- <result column=\"gender\" property=\"gender\">result>
- <result column=\"address\" property=\"address\">result>
- <collection property=\"ordersList\" ofType=\"com.liuyanzhao.mybatis.po.Orders\">
- <id column=\"id\" property=\"id\">id>
- <result column=\"user_id\" property=\"userId\">result>
- <result column=\"number\" property=\"number\">result>
- <result column=\"createtime\" property=\"createTime\">result>
- <result column=\"node\" property=\"node\">result>
- <collection property=\"orderdetails\" ofType=\"com.liuyanzhao.mybatis.po.Orderdetail\">
- <id column=\"orderdetail_id\" property=\"id\">id>
- <result column=\"items_id\" property=\"itemsId\">result>
- <result column=\"items_num\" property=\"itemsNum\">result>
- <result column=\"orders_id\" property=\"ordersId\">result>
- <association property=\"items\" javaType=\"com.liuyanzhao.mybatis.po.Items\">
- <id column=\"items_id\" property=\"id\">id>
- <result column=\"items_name\" property=\"name\">result>
- <result column=\"items_price\" property=\"price\">result>
- <result column=\"items_detail\" property=\"detail\">result>
- association>
- collection>
- collection>
- resultMap>
- <select id=\"findUserAndItemsResultMap\" resultMap=\"UserAndItemsResultMap\">
- SELECT
- orders.*,
- user.username,
- user.gender,
- user.address,
- orderdetail.id orderdetail_id,
- orderdetail.items_id,
- orderdetail.items_num,
- orderdetail.orders_id,
- items.name items_name,
- items.detail items_detail,
- items.price items_price
- FROM
- orders,
- user,
- orderdetail,
- items
- WHERE orders.user_id=user.id AND orders.id = orderdetail.orders_id AND orderdetail.items_id=items.id
- select>
- mapper>
4、测试类 OrderMapperCustomTest.java
- package com.liuyanzhao.mybatis.test;
- import com.liuyanzhao.mybatis.mapper.OrdersMapperCustom;
- import com.liuyanzhao.mybatis.po.User;
- import org.apache.ibatis.io.Resources;
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.apache.ibatis.session.SqlSessionFactoryBuilder;
- import org.junit.Before;
- import org.junit.Test;
- import java.io.InputStream;
- import java.util.List;
- /**
- * Created by Liu_Yanzhao on 2017/8/12.
- */
- public class OrderMapperCustomTest {
- SqlSessionFactory sqlSessionFactory;
- @Before
- public void setUp() throws Exception {
- String resource = \"Configuration.xml\";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- sqlSessionFactory = new SqlSessionFactoryBuilder()
- .build(inputStream);
- }
- @Test
- public void testFindUserAndItemsResultMap() throws Exception {
- SqlSession sqlSession = sqlSessionFactory.openSession();
- //创建代理对象
- OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
- //调用mapper对象
- List
list = ordersMapperCustom.findUserAndItemsResultMap(); - System.out.println(list);
- //释放资源
- sqlSession.close();
- }
- }
还有其他文件就不补充了,如 mybatis 全局配置文件
小结
这样多对多的映射就搞定了。不过还有个问题,就是这里多对多的查询会把所有关联的表的信息都查询出来,然后放到pojo中的对应的List或者某个类中,所以即使我只查了个用户信息,但是这个用户里包含了订单,订单项,商品等信息,感觉装的有点多,好像有时候并不需要这么多冗余的数据出来,但是如果用resultType的话查询出来的字段必须对应pojo中的属性,如果有List等,需要手动装入才行。所以下面总结一下对于这种查询数据比较多的时候,resultType和resultMap各有什么作用?
- 比如我们只需要将查询用户购买的商品信息明细清单(如用户名、用户地址、购买商品名称、购买商品时间、购买商品数量),那么我们完全不需要其他的信息,这个时候就没必要使用resultMap将所有的信息都搞出来,我们可以自己定义一个pojo,包含我们需要的字段即可,然后查询语句只查询我们需要的字段,这样使用resultType会方便很多。
- 如果我们需要查询该用户的所有详细信息,比如用户点击该用户或者鼠标放上去,会出来跟该用户相关的订单啊,订单明细啊,商品啊之类的,然后我们要点进去看下详细情况的时候,那就需要使用resultMap了,必须将所有信息都装到这个User中,然后具体啥信息再从User中取,很好理解。
- 总结一点:使用resultMap是针对那些对查询结果映射有特殊要求的功能,,比如特殊要求映射成list中包括多个list。否则使用resultType比较直接。
到这里,mybatis的多对多映射就总结完了。
发表评论: