三层多对多关系查询方法

场景描述

        假设模仿健康体检的项目场景,体检的各个项目称为检查项,多个检查项能够组成一个体检组,例如普通检查组包括了身高、体重、血压等等的体检项。同时多个检查组能够组成一个检查套餐。
        三者之间的关系是多对多的关系,同一个检查项可以在不同的检查组,同一个检查组可以在不同的检查套餐。

实现效果

        通过给出一个检查套餐的id值,能够查出其包含的所有检查组,同时根据这些检查组能够查出每个检查组里面的检查项的详细信息,就是对两重的多对多关系的查询。

前期准备

        根据场景的描述,先准备体检项、体检组、体检套餐的POJO类,对应的持久层的配置文件。这里采用的是MyBatis作为持久层框架,通过编写Dao的xml配置文件来实现对数据库的操作。
        列出了检查项、检查组和套餐的数据表表名和类的名称。

检查项检查组套餐
数据库表名tab_inspectitemtab-inspectgrouptab_setmeal
POJO类InspectItemInspectGroupSetmeal
*Dao.xmlInspectItemDao.xmlInspectGroupDao.xmlSetmealDao.xml

        检查项、检查组和套餐的中间表的名称。

tab_inspectgroup_inspectItem #检查项与检查组关联的中间表

tab_setmeal_inspectgroup #检查项与检查组关联的中间表

POJO的InspectItem 类

import java.io.Serializable;

/**
 * 检查项
 */
public class InspectItem implements Serializable {
    private Integer id;//主键
    private String code;//项目编码
    private String name;//项目名称
    private String sex;//适用性别
    private String age;//适用年龄(范围),例如:20-50

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

InspectGroup类

import java.io.Serializable;
import java.util.List;

/**
 * 检查组
 */
public class InspectGroup implements Serializable {
    private Integer id;//主键
    private String code;//编码
    private String name;//名称
    private String sex;//适用性别
    private List<InspectItem > inspectItems;//一个检查组合包含多个检查项

    public List<InspectItem > inspectItems() {
        return inspectItems;
    }

    public void setInspectItems(List<InspectItem> inspectItems) {
        this.inspectItems= inspectItems;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

   
    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

Setmeal类

import java.io.Serializable;
import java.util.List;

/**
 * 体检套餐
 */
public class Setmeal implements Serializable {
    private Integer id;
    private String name;
    private String code;
    private String sex;//套餐适用性别:0不限 1男 2女
    private String age;//套餐适用年龄
    private List<InspectGroup> inspectGroups;//体检套餐对应的检查组,多对多关系

    public List<InspectGroup> getInspectGroups() {
        return inspectGroups;
    }
    public void setInspectGroups(List<InspectGroup> inspectGroups) {
        this.inspectGroups = inspectGroups;
    }
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

实现过程

        根据要达到的要求,通过service层调用dao层的方法,可以根据Setmeal的id来查找套餐的详细内容,Setmeal的属性包含了一个装有InspectGroup类的list集合,而且InspectGroup类中也包含了一个装有InspectItem类的list集合。
        这一连串的查找都是通过传入一个Setmeal的id来触发的。
        假设Setmeal的service层调用了SetmealDao的 findById() 方法。

<?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.gochen.dao.SetmealDao">
    
    <resultMap id="BaseResultMap" type="com.gochen.pojo.Setmeal">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="code" property="code"/>
        <result column="sex" property="sex"/>
        <result column="age" property="age"/>
    </resultMap>
    <!-- 
			collection定义关联集合类型的属性的封装规则 
			ofType:指定集合里面元素的类型
		-->
    <resultMap id="findByIdResultMap" type="com.gochen.pojo.Setmeal" extends="BaseResultMap">
        <collection property="inspectGroups" javaType="ArrayList" ofType="com.gochen.pojo.InspectGroup"
                    column="id"
                    select="com.gochen.dao.InspectGroupDao.findInspectGroupById"></collection>
    </resultMap>

    <select id="findById" parameterType="int" resultMap="findByIdResultMap">
        select * from t_setmeal where id = #{id}
    </select>
</mapper>

        因为存在着多对多的关系,同时也要查出所有的数据,所以不能单单用resultType来决定返回值的类型,所以要定义自己的返回值的结果集,即使用了resultMap。

        将resultMap映射为 findByIdResultMap ,在 findByIdResultMap 中通过extends属性继承了Setmeal的基础 BaseResultMap 来查找Setmeal其他属性的值。

        在 findByIdResultMap 中的属性 column="id" ,将list集合中的 InspectGroup 的id传到属性select中描述的 InspectGroupDao.findInspectGroupById 来查找InspectGroup的详细内容。

        因为 findInspectGroupById() 方法来自InspectGroupDao,所以看InspectGroupDao.xml的配置信息:

<?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.gochen.dao.InspectGroupDao">

    <resultMap id="BaseResultMap" type="com.gochen.pojo.InspectGroup">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="code" property="code"/>
        <result column="sex" property="sex"/>
    </resultMap>
    <resultMap id="findByIdResultMap" type="com.gochen.pojo.InspectGroup">
        <collection property="inspectItems" javaType="ArrayList" ofType="com.gochen.pojo.InspectItem"
                    column="id"
                    select="com.gochen.dao.InspectItemDao.findInspectItemById"></collection>
    </resultMap>


    <select id="findInspectGroupById" parameterType="int" resultMap="findByIdResultMap">
        select * from t_inspectgroup where id in (select inspectgroup_id from t_setmeal_inspectgroup where setmeal_id = #{id})
    </select>
</mapper>

        在InspectGroupDao.xml中的查找方法是SetmealDao.xml指定的方法,这时id就会传进去,也就是 检查组的id ,进而查找其装有InspectItem类的list集合里面的id,然后传到 InspectItemDao.findInspectItemById() 的方法中,其调用的流程和SetmealDao.xml调用的过程一样,这里就不赘述了。

        最后就到InspectItemDao.xml配置信息了:

<?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.gochen.dao.InspectItemDao">

    <select id="findInspectItemById" parameterType="int" resultType="com.gochen.pojo.InspectItem">
        select * from t_inspectitem where id in (select inspectitem_id from t_inspectgroup_inspectitem where inspectgroup_id = #{id})
    </select>

</mapper>

        到这里,检查项已经是最小项了,所以在InspectItemDao.xml中只要实现 findInspectItemById() 方法就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是哈猿啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值