MyBatis_多表查询的结果封装


实际开发中有很多多表查询的情况,下面来学习多表查询如何传递参数,如何接收返回结果。

其实参数传递无论是单表还是多表操作都是一样的,可以使用map或者pojo对象传参

但是接收返回结果的方式就不一样了,因为涉及到多张表(不同类类型)的结果,因此多表查询的重点在于如何接收查询结果

  • 多表查询封装结果的3种方式
  1. 使用resultMap绑定表中列和类属性关系,接收多对一的查询结果
  2. 使用resultMap+嵌套select查询,接收一对多的查询结果
  3. 使用VO(view Object)对象接收一对多的查询结果
  • 多表查询的分类
    • 多对一查询 / 一对一
    • 一对多查询 / 多对多

8.1. 多对一查询

  • 区分多对一关系数据的特点

    数据A 有一个 数据B ,多个A可以有同一个B。

  • 案例:查询订单时,展示对应的用户信息

    1. 确定查询需求是否属于多对一
    2. 准备多对一环境(表、类)
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接收
  1. 编写mapper接口方法
  2. 编写statement
  3. 编写resultMap
  4. 测试
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">
        <id property="uid" column="uid"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="phone" column="phone"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
    </association>
</resultMap>
4. 测试
/**
  * 多对一查询:多个订单对应一个用户
  */
@Test
public void listOrderAndUser(){
    //获取sqlSession链接
    SqlSession sqlSession = MyBatisUtils.getSession();

    OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
    List<Orders> orders = mapper.listOrderAndUser();

    //关闭链接
    MyBatisUtils.closeSession();
}
总结
  1. 多对一查询通过resultMap自定义结果映射封装查询结果
  2. association定义多对一或者一对一的关系
8.1.4. 使用嵌套select查询
  1. 修改resultMap,添加嵌套select
  2. 编写statement
  3. 编写接口方法
  4. 测试
1. 编写resultMap+嵌套select
<!--使用resultMap+嵌套select进行关联查询-->
<resultMap id="resultMapBySelect" 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定义多对一或者一对一的关系-->
    <!--
        嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
        当查询Order表中数据的时候,会级联查询对应的user表中的数据,
        并将查询结果封装到user属性中
        -->
    <association property="user"
                 select="selectUserByID"
                 column="user_id">
    </association>
</resultMap>
2. 编写statement
<!--嵌套select用到的statement-->
<select id="selectUserByID" resultType="user">
    SELECT
    uid,
    username,
    birthday,
    phone,
    sex,
    address
    FROM `user`
    WHERE uid = #{uid}
</select>

<!--多对一查询:查询订单时,通过resultMap中的嵌套select 关联查询用户-->
<!--注意,这里就不需要自己再去查询关联对象的数据了,因为resultMap中已经嵌套查询了-->
<select id="listOrder" resultMap="resultMapBySelect">
    SELECT
    order_id,
    user_id,
    order_price,
    payment,
    state,
    order_createtime,
    note
    FROM orders
</select>
3. 编写Mapper接口方法
public List<Orders> listOrder();
4. 测试
/**
  * 多对一查询:使用嵌套select
  */
@Test
public void listOrder(){
    //获取sqlSession链接
    SqlSession sqlSession = MyBatisUtils.getSession();

    OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
    List<Orders> orders = mapper.listOrder();

    //关闭链接
    MyBatisUtils.closeSession();
}
总结
  1. 嵌套select使用关联查询来获取关联的对象数据
  2. statement中不需要查询关联表,因为嵌套select会在查询时被执行
  3. 嵌套select会查询关联表的所有列
8.1.5. 使用VO类接收

多表查询无非是结果属于不同类的属性,所以前面用resultMap来指定关联的属性如何接收,如果有一个类的属性能和查询结果的列都对应上,那就不用编写resultMap那么麻烦了。
在这里插入图片描述

  • 使用VO类接收多表查询结果
  1. 新增VO类
  2. 编写mapper接口方法
  3. 修改statement为resultType=“VO类型”
1. 新增VO类

VO类拥有查询结果列对应的全部属性

public class OrderVO extends Orders {
    private Integer uid;
    private String username;
    private String phone;
    
    //get set...
}
2. 修改statement的resultType
<!--多对一查询:多个订单对应一个用户-->
<!--使用自定义VO类接收返回值-->
<select id="listOrderAndReturnOrdersVO" resultType="com.czxy.mybatis.vo.OrderVO">
    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. mapper接口方法
//使用自定义VO接收返回结果
public List<OrderVO> listOrderAndReturnOrdersVO();
4. 测试
/**
  * 多对一查询
  * 使用自定义VO类接收返回结果
  */
@Test
public void listOrderAndReturnOrderVO(){
    //获取sqlSession链接
    SqlSession sqlSession = MyBatisUtils.getSession();

    OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
    //返回结果是VO类型
    List<OrderVO> list = mapper.listOrderAndReturnOrdersVO();

    //关闭链接
    MyBatisUtils.closeSession();
}
  • 小提示:toString()方法默认只能打印本类的属性,因此调试查看结果需要展开查看
    在这里插入图片描述

8.2. 一对多查询

  • 一对多的数据结构特点

    一对多的数据都是树状结构展示:展示A数据,下方展示多个A对应的B数据
    在这里插入图片描述

  • 一对多示例

    • 一个父分类对应多个子分类
      在这里插入图片描述
  • 一个品牌对应多个类别

  • 一个品牌对应多个商品
    在这里插入图片描述

  • 案例:查询某品牌时,对应查询该品牌所有商品

    确定查询需求是否属于一对多

    准备一对多环境(表、类)

  • 使用3种方式封装查询结果

  1. 使用resultMap绑定表中列和类属性关系,接收一对多的查询结果
    1. 编写SQL片段
    2. 编写resultMap封装查询结果
    3. 编写mapper接口方法
    4. 测试
  2. 使用resultMap+嵌套select查询,接收一对多的查询结果
    1. 修改resultMap,添加嵌套查询
    2. 测试
  3. 使用VO对象接收一对多的查询结果
    1. 新建VO类
    2. 编写SQL片段为resultType=“VO类型”
    3. 测试
8.2.1. 确定查询需求

查询某品牌时,对应查询该品牌所有商品

前面已经明确一个品牌对应多个商品,属于一对多查询

8.2.2. 准备一对多环境(表、类)
  • 品牌表、商品表
/*Table structure for table `brands` */
CREATE TABLE `brands` (
  `brand_id` int NOT NULL AUTO_INCREMENT COMMENT '品牌ID',
  `brand_name` varchar(100) DEFAULT NULL COMMENT '品牌名称',
  `brand_img` varchar(150) DEFAULT NULL COMMENT '品牌图标',
  PRIMARY KEY (`brand_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

/*Data for the table `brands` */

insert  into `brands`(`brand_id`,`brand_name`,`brand_img`) values (1,'瑞士莲','/img/lindt_chocolate.img'),(2,'德芙','/img/dove.img'),(3,'费列罗','/img/FERRERO_ROCHER.img');

/*Table structure for table `product` */
CREATE TABLE `product` (
  `product_id` varchar(32) NOT NULL COMMENT '商品ID',
  `product_img` varchar(50) DEFAULT NULL COMMENT '商品图片',
  `product_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '商品名称',
  `product_sale` int DEFAULT NULL COMMENT '商品销量',
  `stock` int DEFAULT NULL COMMENT '商品库存',
  `product_price` double DEFAULT NULL COMMENT '商品价格',
  `brandid` int DEFAULT NULL COMMENT '品牌ID',
  PRIMARY KEY (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `product` */

insert  into `product`(`product_id`,`product_img`,`product_name`,`product_sale`,`stock`,`product_price`,`brandid`) values ('p01','/img/dove/213231.img','Dove/德芙丝滑牛奶巧克力252g碗装排块糖果糖巧休闲零食品',1800062,2000000,29.9,2),('p02','/img/dove/352342.img','德芙麦提莎麦丽素麦芽脆夹心巧克力豆520g/桶装休闲零食糖果',209710,300000,79.9,2),('p03','/img/dove/635987.img','Dove/德芙丝滑牛奶巧克力252g*2碗装排块休闲零食品糖果',344410,500000,59.8,2),('p04','/img/rocher/845127.img','费列罗榛果巧克力48粒送女友零食婚庆礼盒3*16条喜糖糖果礼',563315,1000000,139,3),('p05','/img/rocher/345311.img','费列罗拉斐尔椰蓉扁桃仁糖果酥球10粒 休闲零食',19460,25000,79.9,3);

  • 品牌类、商品类
/**
 * 品牌
 */
public class Brands {
    private Integer brandId;	//品牌ID
    private String brandName;	//品牌名称
    private String brandImg;	//品牌图片

    //关联商品:一对多
    private ArrayList<Product> listProduct = new ArrayList<>();
    
    //get set ...
}

/**
 * 商品
 */
public class Product {

    private String productId;	//商品ID
    private String productImg;	//商品图片
    private String productName;	//商品名称
    private Integer productSale;	//商品销量
    private Double productPrice;	//商品价格

    //关联品牌:多对一
    private Brands brand;
    //get set ...
}
8.2.3. 使用resultMap接收
1. 编写mapper接口方法
public interface BrandMapper {
    //查询某个品牌,以及品牌对应的商品
    public Brands selectBrandAndProducts(Integer brandId);
}
2. 编写SQL片段
  1. 查询品牌以及对应所有商品SQL
SELECT
	b.brand_id,
	b.brand_img,
	b.brand_name,
	p.product_id,
	p.product_img,
	p.product_name,
	p.product_price,
	p.product_sale
FROM brands b,product p
WHERE b.brand_id = p.brandid
AND b.brand_id = 2
  1. 编写SQL片段
    <select id="selectBrandAndProducts" resultMap="baseResultMap">
        SELECT
            b.brand_id,
            b.brand_img,
            b.brand_name,
            p.product_id,
            p.product_img,
            p.product_name,
            p.product_price,
            p.product_sale
        FROM brands b,product p
        WHERE b.brand_id = p.brandid
        AND b.brand_id = #{brandID}
    </select>
3. 编写resultMap
<!--type:返回的数据类型,一对多,这里写一的类型-->
<resultMap id="baseResultMap" type="brands">
    <!--Brands类属性和brands表中列的关系绑定-->
    <id property="brandId" column="brand_id"></id>
    <result property="brandName" column="brand_name"></result>
    <result property="brandImg" column="brand_img"></result>
    <!--collection定义一对多或者对多多的关系-->
    <!--
       ofType” 属性。这个属性非常重要,
       它用来将 JavaBean(或字段)属性的类型和集合存储的类型区分开来。
     -->
    <collection property="listProduct" ofType="product">
        <!--品牌Product类属性和表product中列绑定关系-->
        <id property="productId" column="product_id" ></id>
        <result property="productImg" column="product_img"></result>
        <result property="productName" column="product_name"></result>
        <result property="productSale" column="product_sale"></result>
        <result property="productPrice" column="product_price"></result>
    </collection>
</resultMap>

  • 别忘了在mybatis-config.xml加入BrandMapper.xml
    <!--映射器-->
    <mappers>
        <!--加载映射文件的位置-->
        <!-- 这里省略了其他映射文件 -->
        <mapper resource="mapper/BrandMapper.xml"/>
    </mappers>
4. 测试
/**
  * 一对多查询
  */
@Test
public void selectBrandAndProducts(){
    //获取sqlSession链接
    SqlSession sqlSession = MyBatisUtils.getSession();

    //调用mapper接口的查询方法
    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
    Brands brands = mapper.selectBrandAndProducts(2);

    //关闭链接
    MyBatisUtils.closeSession();
}
8.2.4. 使用嵌套select接收
  1. 编写resultMap
  2. 编写statement
  3. 编写mapper接口方法
  4. 测试
1. 编写resultMap
  • BrandMapper.xml 编写resultMap+嵌套select
<!-- 提取公共的resultMap -->
<resultMap id="baseResultMap" type="brands">
    <!--Brands类属性和brands表中列的关系绑定-->
    <id property="brandId" column="brand_id"></id>
    <result property="brandName" column="brand_name"></result>
    <result property="brandImg" column="brand_img"></result>
</resultMap>

<!--extends: 继承公用的resultMap-->
<resultMap id="resultMapBySelect" type="brands" extends="baseResultMap">
    <!--collection定义一对多或者对多多的关系-->
    <!--嵌套select: 当查询品牌时,嵌套select会查询对应商品数据,将结果封装到Product属性中-->
    <!--select:调用ProductMapper的方法,以brand_id的值作为参数进行查询-->
    <collection property="listProduct"
                column="brand_id"
                select="com.czxy.mybatis.mapper.ProductMapper.listProductsByBrandID">
    </collection>
</resultMap>
  • ProductMapper.xml 添加根据brandid查询的statement
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czxy.mybatis.mapper.ProductMapper">

    <select id="listProductsByBrandID" resultType="product">
        SELECT
            product_id,
            product_img,
            product_name,
            product_sale,
            stock,
            product_price,
            brandid
        FROM product
        WHERE brandid = #{brandID}
    </select>

</mapper>
2. 编写statement

BrandMapper.xml

<!--使用嵌套select接收查询结果-->
<!--嵌套select会查询product,这里就不需要关联查询product-->
<select id="selectBrandAndListProducts" resultMap="resultMapBySelect">
    SELECT
        brand_id,
        brand_img,
        brand_name
    FROM brands
    WHERE brand_id = #{brandID}
</select>
  • mybatis-config.xml 加载mapper.xml
<!--映射器-->
<mappers>
    <!--加载映射文件的位置-->
    <mapper resource="mapper/UserMapper.xml"/>
    <mapper resource="mapper/OrderMapper.xml"/>
    <mapper resource="mapper/BrandMapper.xml"/>
    <mapper resource="mapper/ProductMapper.xml"/>
</mappers>
3. mapper接口方法
//查询某个品牌,以及品牌对应的商品:使用嵌套select查询
public Brands selectBrandAndListProducts(Integer brandId);
4. 测试
/**
 * 一对多查询
 * 使用嵌套select查询
 */
@Test
public void selectBrandAndListProducts(){
    //获取sqlSession链接
    SqlSession sqlSession = MyBatisUtils.getSession();

    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
    Brands brands = mapper.selectBrandAndListProducts(2);

    //关闭链接
    MyBatisUtils.closeSession();
}
8.2.5. 使用自定义VO接收

一对多不能使用VO类接收…,因为一对多的查询结果是个集合…

其实一对多可以分2次单表查询来实现,例如查询品牌时,查询品牌下的所有商品

  • 第一次根据品牌ID查询品牌
  • 第二次根据品牌ID查询商品
- 第一次根据品牌ID查询品牌
<select id="">
    //...
</select>
- 第二次根据品牌ID查询商品
<select id="">
    //...
</select>

8.3. 多对多查询

多对多查询和一对多查询几乎一样

案例:一个老师会教多个学生,一个学生有多个老师

需求:查询学生对应的老师有哪些

  • 实现步骤
  1. 准备环境:
    1. 添加老师学生相关表
    2. 添加老师学生相关类
  2. 编写resultMap封装多表查询结果
  3. 编写statement完成多表查询
  4. 编写接口方法
  5. 测试
8.3.1. 准备多表查询环境
/*Table structure for table `tab_student` */

DROP TABLE IF EXISTS `tab_student`;

CREATE TABLE `tab_student` (
  `sid` int NOT NULL AUTO_INCREMENT COMMENT '学生ID',
  `student_name` varchar(30) DEFAULT NULL COMMENT '姓名',
  `student_birthday` date DEFAULT NULL COMMENT '生日',
  `student_height` double DEFAULT NULL COMMENT '身高',
  `sex` varchar(2) DEFAULT NULL COMMENT '性别',
  PRIMARY KEY (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

/*Data for the table `tab_student` */

insert  into `tab_student`(`sid`,`student_name`,`student_birthday`,`student_height`,`sex`) values (1,'褚英才','1997-02-01',175,'男'),(2,'绍洋','1999-08-21',160,'女'),(3,'司徒玉','2000-10-12',162,'女'),(4,'孟杨','1999-06-08',172,'男'),(5,'郎桂芝','1998-10-26',168,'女');

/*Table structure for table `tab_student_teacher` */

DROP TABLE IF EXISTS `tab_student_teacher`;

CREATE TABLE `tab_student_teacher` (
  `id` int NOT NULL AUTO_INCREMENT,
  `sid` int DEFAULT NULL COMMENT '学生ID',
  `tid` varchar(32) DEFAULT NULL COMMENT '老师ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

/*Data for the table `tab_student_teacher` */

insert  into `tab_student_teacher`(`id`,`sid`,`tid`) values (1,1,'T001'),(2,2,'T001'),(3,1,'T002'),(4,3,'T002'),(5,5,'T002'),(6,2,'T003');

/*Table structure for table `tab_teacher` */

DROP TABLE IF EXISTS `tab_teacher`;

CREATE TABLE `tab_teacher` (
  `tid` varchar(32) NOT NULL COMMENT '老师ID',
  `tname` varchar(30) DEFAULT NULL COMMENT '姓名',
  `tsex` varchar(3) DEFAULT NULL COMMENT '性别',
  PRIMARY KEY (`tid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `tab_teacher` */

insert  into `tab_teacher`(`tid`,`tname`,`tsex`) values ('T001','韩老师','男'),('T002','董老师','男'),('T003','茆老师','女');

public class Teacher {

    private String tid;
    private String tname;
    private String tsex;
    //老师对应多个学生
    List<Student> stuList = new ArrayList<Student>();
    
    //get set...
}    
public class Student {
    private Integer sid;
    private String studentName;
    private Date studentBirthday;
    private Double studentHeight;
    private String sex;

    //学生对应多个老师
    private List<Teacher> teacherList = new ArrayList<>();
    //get set...
}   
8.3.2. StudentMapper.xml
<resultMap id="studentBaseMap" type="student">
    <id property="sid" column="sid"/>
    <result property="studentName" column="student_name"/>
    <result property="studentBirthday" column="student_birthday"/>
    <result property="studentHeight" column="student_height"/>
    <result property="sex" column="sex"/>
    <collection property="teacherList" ofType="Teacher">
        <id property="tid" column="tid"/>
        <result property="tname" column="tname"/>
        <result property="tsex" column="tsex"/>
    </collection>
</resultMap>

<select id="selectStudentAndTeachers" resultMap="studentBaseMap">
    SELECT
    s.sid,
    s.student_name,
    s.student_birthday,
    s.student_height,
    s.sex,
    t.tid,
    t.tname,
    t.tsex
    FROM tab_student s,tab_student_teacher st,tab_teacher t
    WHERE s.sid = st.sid
    AND st.tid = t.tid
    AND s.sid = #{sid}
</select>
8.3.3. 接口方法
public interface StudentMapper {

    public List<Student> selectStudentAndTeachers(Integer sid);
}
8.3.4. 测试
/**
  * 多对多查询
  */
@Test
public void selectStudentById(){
    //获取sqlSession链接
    SqlSession sqlSession = MyBatisUtils.getSession();
    //获取mapper接口
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    List<Student> student = mapper.selectStudentAndTeachers(2);

    sqlSession.close();
}

附件 - jdbcType 类型

为了以后可能的使用场景,MyBatis 通过内置的 jdbcType 枚举类型支持下面的 JDBC 类型。

BIT FLOAT CHAR TIMESTAMP OTHER UNDEFINED
TINYINT REAL VARCHAR BINARY BLOB NVARCHAR
SMALLINT DOUBLE LONGVARCHAR VARBINARY CLOB NCHAR
INTEGER NUMERIC DATE LONGVARBINARY BOOLEAN NCLOB
BIGINT DECIMAL TIME NULL CURSOR ARRAY

猜你喜欢

转载自blog.csdn.net/qq_44509920/article/details/107585892