百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

记录学习——三层多对多关系查询方法

ccwgpt 2024-10-09 08:48 29 浏览 0 评论

场景描述

假设模仿健康体检的项目场景,体检的各个项目称为检查项,多个检查项能够组成一个体检组,例如普通检查组包括了身高、体重、血压等等的体检项。同时多个检查组能够组成一个检查套餐。

三者之间的关系是多对多的关系,同一个检查项可以在不同的检查组,同一个检查组可以在不同的检查套餐。

实现效果

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

前期准备

根据场景的描述,先准备体检项、体检组、体检套餐的POJO类,对应的持久层的配置文件。这里采用的是MyBatis作为持久层框架,通过编写Dao的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() 方法就行了。

相关推荐

Python元类实现自动化编程的正确姿势

元类是Python中用于创建类的类。通过元类机制,开发者可在运行时动态创建和修改类,为框架开发、设计模式实现和高级架构设计提供核心支持。在Python语言的高级特性中,元类占据着独特而重要的地位。作...

快速入门Python办公自动化:让效率提升10倍的实用指南

引言在数字化办公时代,握Python自动化技能已成为职场竞争力的关键指标。本文将通过系统化的知识框架,带您从零基础快速掌握Python办公自动化核心技能。一、Python办公自动化核心优势跨平台兼容性...

一文掌握怎么利用Python+Shell构建一个自动化的数据处理系统

简介:本文系统讲解了如何利用Python与Shell脚本相结合,构建一个高效、自动化的数据处理系统。文章从项目结构设计、核心功能实现到Web管理界面的搭建,详细介绍了数据采集、清洗、分析、入库和报表展...

自动化数据可视化,用Python帮你把数据变“画”

阅读文章前辛苦您点下“关注”,方便讨论和分享,为了回馈您的支持,我将每日更新优质内容。如需转载请附上本文源链接!一、数据可视化,为什么非得自动化?做数据分析,光看一堆数字和表格,眼睛都累趴了。得靠数据...

从理论到实战,如何快速掌握 Swift 开发?

Swift语言是苹果全力推广的语言,相对于Objective-C,Swift语法更简洁,类型更安全。另外,它还增加了诸如可选值、泛型、协议扩展等特性,在开发实践中比Objective-C更具...

Swift 3 API 设计准则(api swiftpay solutions)

本文由星夜暮晨(简书)翻译自苹果Swift官方网站2015年12月4日一款编程语言标准库的设计理念,往往对这门编程语言给人的整体感觉有很大影响。好的标准库就好似语言本身的扩展一般,并且保证标准库内...

让你的App消息分发又快又稳:EventBus框架核心原理与

让你的App消息分发又快又稳:EventBus框架核心原理与实现全流程在上一篇文章中,我们详细剖析了观察者模式的各种实现方式及其应用场景。今天,我们聚焦一个更工程化、更实用的高阶用法:如何在移动端实现...

Flutter 的推荐架构:为什么不是 BLoC?

最近,Flutter团队发布了一份架构指南,建议开发者采用MVVM(Model-View-ViewModel)模式来组织Flutter应用的层级结构。这个模式在原生Kotlin和Swi...

苹果或将解决SwiftUI的两大盲点(swift apple)

#万能生活指南#快速导读苹果的SwiftUI框架即将迎来重要升级,彭博社的马克·古尔曼指出,开发者将获得内置的富文本编辑器和本地网页视图嵌入API。这些改进将显著提升开发者在应用开发中的体验,特...

曝苹果带屏HomePod今年发:7英寸天马显示屏

据消息源最新爆料,苹果一款7英寸的带屏HomePod会在今年正式推出,屏幕由国产供应商天马提供,这也是天马第一次打入苹果供应链体系。该消息源表示,带屏HomePod是苹果今年最重磅的产品之一,它是苹果...

苹果 Containerization 提供了面向 macOS 的原生 Linux 容器支持

作者|ClaudioMasolo策划|张卫滨苹果在2025年的全球开发者大会(WWDC)上发布了Containerization和ContainerCLI,这是一个在Mac...

苹果用Swift重写服务:性能飞升,内存代码“断崖式”下降!

苹果工程师近日分享了他们用Swift重写Java服务器端应用的经历。据介绍,这个服务器端应用是“密码监视”功能的核心组件,原本采用Java实现,每天需要处理来自世界各地设备的数十亿次请求。...

Apple 完成关键生态系统服务向 Swift 的迁移,性能提升 40%

苹果已将其全球密码监控服务从Java迁移到Swift,实现了吞吐量40%的增长,并显著减少了内存使用量,释放了之前分配的近50%的Kubernetes容量。在最近的一篇文章中,苹果...

苹果 Swift 编程语言现已正式扩展 支持 Android 应用开发

通过在Swift开源项目内部成立专门的Android工作组,苹果的Swift编程语言现已正式扩展,以支持Android应用开发。Swift最初由苹果于2014年推出,作为iOS...

苹果开发团队弃用Java,改用自家Swift重写关键服务

IT之家6月5日消息,科技媒体devclass昨日(6月4日)发布博文,报道称由于Java的内存管理方式无法满足日益增长的需求和效率目标,苹果内部团队决定使用更高效的编程语言S...

取消回复欢迎 发表评论: