MyBatis多表级联查询

关系:

  • 1,班级和学生:班级1--n学生 (一对多关系)

1个班级--》n(多)个学生,,1个学生--》(同一时间)1个班级

这样,多对一的学生表需要持有班级的 外键

  1. 2,学生和学籍档案(一对一关系)

1个学生--》1份档案,,1份档案--》1个学生

这样,1对1的关系通常通过主键进行关联(1号学生-对应-》1号档案)

  • 3,学生和课程的关系(多对多关系)

1个学生--》n课程,,1个课程--》你个学生

这样多对多的关系--》设计数据表时需要出现出一个 中间表 ,中间表持有课程和学生的编号,学生表与中间表关联,课程表与中间表关联,这样三张表就构建起一个多对多关系。

使用场景案例:(一对多)

使用场景案例:(一对多)

1、一个商品基本信息表:t_goods,主键是good_id

2、一个商品图片表:t_goods_detail,外键是good_id

3、一个商品有多个商品图片

4、我们希望在查询这个商品的信息的同时,把该商品的商品图片也查询出来,

5、商品与商品图片是一对多的关系,商品可以有多个商品图片,而一个商品图片只能有一个对应的商品。

步骤:1、创建商品实体类Goods、创建商品图片表实体类GoodsDetail
public class Goods {
    .....
    private List<GoodsDetail> goodsDetails;
    .....
}    
步骤:2、创建Goods mappers文件goods.xml、创建GoodsDetail mappers文件goods_detail.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="goods">
     <!--resultMap结果映射,说明GoodsDetail List集合数据从哪来的-->
    <resultMap id="rmGoods2" type="top.xiongmingcai.entity.Goods">
        <!--设置主键字段:属性名、字段名-->
        <id property="goods_id" column="goods_id"></id>
        <!--设置collection:集合属性名、生成集合的SQL、关联主键-->
        <collection property="goodsDetails" select="goodsDetail.selectByGoodsId" column="goods_id"/>
    </resultMap>    <!--关联查询,resultMap结果映射到rmGoods-->
    <select id="selectOneToMany" resultMap="rmGoods2">
        select * from t_goods limit 0,3
    </select>
</mapper>
<?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="goodsDetail">

    <select id="selectByGoodsId" parameterType="Integer" resultType="top.xiongmingcai.entity.GoodsDetail">
        select *
        from t_goods_detail
        where goods_id = #{value}
    </select>
</mapper>
3、在SqlSession执行select语句:
public class MyBatisUtilsTest {
    static SqlSession sqlSession = null;

    @AfterClass
    public static void afterClass() throws Exception {
        MyBatisUtils.closeSession(sqlSession);
    }

    @BeforeClass
    public static void beforeClass() throws Exception {
        sqlSession = MyBatisUtils.openSession();
    }
    @Test
    public void selectOneToMany() {
        List<Goods> list = sqlSession.selectList("goods.selectOneToMany");
        for (Goods goods:list){
            System.out.println(goods.getTitle()+":"+goods.getGoodsDetails().size());
        }
    }
}    

output

914  [main] DEBUG goods.selectOneToMany - ==>  Preparing: select * from t_goods limit 0,3  
971  [main] DEBUG goods.selectOneToMany - ==> Parameters:  
1028 [main] DEBUG goodsDetail.selectByGoodsId - ====>  Preparing: select * from t_goods_detail where goods_id = ?  
1033 [main] DEBUG goodsDetail.selectByGoodsId - ====> Parameters: 741(Integer) 
1056 [main] DEBUG goodsDetail.selectByGoodsId - <====      Total: 6 
1060 [main] DEBUG goodsDetail.selectByGoodsId - ====>  Preparing: select * from t_goods_detail where goods_id = ?  
1061 [main] DEBUG goodsDetail.selectByGoodsId - ====> Parameters: 742(Integer) 
1074 [main] DEBUG goodsDetail.selectByGoodsId - <====      Total: 22 
1075 [main] DEBUG goodsDetail.selectByGoodsId - ====>  Preparing: select * from t_goods_detail where goods_id = ?  
1075 [main] DEBUG goodsDetail.selectByGoodsId - ====> Parameters: 743(Integer) 
1086 [main] DEBUG goodsDetail.selectByGoodsId - <====      Total: 14 
1086 [main] DEBUG goods.selectOneToMany - <==      Total: 3 
斯利安 孕妈专用 洗发水 氨基酸表面活性剂 舒缓头皮 滋养发根 让你的秀发会喝水 品质孕妈:6
亲恩 孕妇护肤品 燕窝补水保湿6件套 孕期安全温和 补水保湿套装:22
优美孕 补水保湿 黄金果水润嫩肤三件套(中样装 洁面乳50g 水50ml 乳液50ml):14

使用场景案例:(多对一)

public class Goods {
    .....
        private Goods goods;//对多持有实体类
    .....
}    
<?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="goodsDetail">
<resultMap id="rmGoodsDetail" type="top.xiongmingcai.entity.GoodsDetail">
        <id property="gpId" column="gd_id"/>
        <result property="goods_id" column="goods_id"/>
        <!--        因为原有的goodsId会作为参数传给联动的SQL,所以这里需要手动为GoodsDetail 的goodsId属性赋值。-->
        <association property="goods" column="goods_id" select="goods.selectById"/>
    </resultMap>
    <select id="selectMangToOne" resultMap="rmGoodsDetail" parameterType="Integer">
        select *
        from t_goods_detail
        where gd_id = #{value } limit 0,1
    </select>
</mapper>
    @Test
    public void selectMangToOne() {
        GoodsDetail goodsDetail = sqlSession.selectOne("goodsDetail.selectMangToOne",9259);
        System.out.println("goodsDetail = " + goodsDetail);
    }

作业

参照MyBatis对象关联查询案例,完成如下功能:

1、创建班级表classes,表结构如下:

2、为班级表添加内容

create table classes
(
    id      int auto_increment
        primary key,
    classno varchar(20) not null,
    name    varchar(20) null,
    major   varchar(20) null
);

insert into babytun.classes (id, classno, name, major)
values  (1, 'Class001', '一班', '计算机'),
        (2, 'Class002', '二班', '计算机'),
        (3, 'Class003', '三班', '会计'),
        (4, 'Class004', '四班', '会计');

3、创建学生表student,表结构如下:

4、为学生表添加如下内容

create table student2
(
    id      int auto_increment
        primary key,
    stuno   varchar(20) not null,
    stuname varchar(20) null,
    sex     varchar(10) not null,
    classno varchar(20) not null
);

insert into babytun.student2 (id, stuno, stuname, sex, classno)
values  (1, '20181101', '梅长苏', '男', 'Class001'),
        (2, '20181102', '萧景琰', '男', 'Class001'),
        (3, '20181103', '宫羽', '女', 'Class001'),
        (4, '20181201', '霓凰', '女', 'Class003');

5、定义实体类和Mapper xml文件,在测试类中查询一班的学生信息并显示(使用一对多关联查询完成)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="classes">

    <select id="selectByClassOne"  resultType="top.xiongmingcai.entity.Classes" parameterType="String">
        select * from classes where trim(classno) =   #{value }
    </select>
    <!--resultMap结果映射,说明GoodsDetail List集合数据从哪来的-->
    <resultMap id="rmClasses" type="top.xiongmingcai.entity.Classes">
        <!--设置主键字段:属性名、字段名-->
        <id property="id" column="id"/>
        <!--设置collection:集合属性名、生成集合的SQL、关联主键-->
        <collection property="student2List" select="student2.selectByClassOne" column="classno"/>
    </resultMap>

    <!--关联查询,resultMap结果映射到rmGoods-->
    <select id="selectByClassOneMany" resultMap="rmClasses">
        select * from classes limit 0,4
    </select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="student2">
    <resultMap id="rmGoodsDetail" type="top.xiongmingcai.entity.Student2">
        <id property="classno" column="classno"/>
        <result property="classno" column="classno"/>
        <!--        因为原有的goodsId会作为参数传给联动的SQL,所以这里需要手动为GoodsDetail 的goodsId属性赋值。-->
        <association property="classes" column="classno" select="classes.selectByClassOne"/>
    </resultMap>
    <select id="selectByClassOne"  resultMap="rmGoodsDetail"  parameterType="String">
        select * from student2 where classno  =   #{value }
    </select>
</mapper>

6、继续完善实体类和Mapper xml文件,在测试类中查询,根据学生查询到班级信息并显示(使用多对一关联查询完成)

   @Test
    public void selectByClassOneMany() {
        List<Classes> classesList = sqlSession.selectList("classes.selectByClassOneMany");
        classesList.forEach(System.out::println);
    }

  @Test
    public void selectByClassOneMany() {
        List<Classes> classesList = sqlSession.selectList("classes.selectByClassOneMany");
        classesList.forEach(System.out::println);
    }