前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >学生信息管理系统开发实战:掌握多数据模型关联关系的设计和使用

学生信息管理系统开发实战:掌握多数据模型关联关系的设计和使用

作者头像
腾讯云开发TCB
发布2024-09-27 14:44:28
970
发布2024-09-27 14:44:28
举报
文章被收录于专栏:云开发

前言

我们日常使用的业务系统,核心都是围绕数据展开,基于数据变化出无穷的可能。本篇文章将基于《学生信息管理系统》这样浅显易懂的场景,介绍如何设计和创建模型,如何在多模型之间建立复杂的关联关系,以及如何在云开发平台中实际操作数据。

1. 数据模型设计范式

1.1 关系型数据库设计范式

数据模型就是基于业务的深刻理解抽象出数据存储的框架,最终落实到实际使用中使数据的读写具有可靠性、扩展性和高效率,从而提升生产效率带来效益。

在传统业务应用开发过程中,首先最重要的是对数据库做好设计构建,其理论依据则是上世纪 70 年代提出的“数据库三范式”:

  • 第一范式(1NF)表中的每一列都是不可拆分的,即保证列的原子性。
  • 第二范式(2NF)表中必须存在主键,且普通字段必须和主键相关,即保证主键列的完全依赖。
  • 第三范式(3NF)表中非主键字段不应互相依赖,即避免依赖传递。

随着时代向前演进,为了满足日益复杂的业务系统要求,范式成员中又陆续新增了BCNF、4NF、5NF 等更多的范式,高阶范式一定满足低阶范式要求且范式设计越高阶,表的精细化越高,冗余度就越低。

1.2 反范式设计

既然数据库范式是减少冗余,那顾名思义,“反范式”就是增加冗余。事实上,在面对有些业务场景时,过于追求范式设计,会将拆分更多原子表,在数据整合时也会更多使用联表操作,联表本身就带来了复杂性和性能损耗,所以适当增加冗余反而更能高效率的完成查询任务,是一种“用空间换时间”的做法。

冗余,在提高查询性能的同时会增加数据写入的难度,通常需要双写或多写来保证冗余字段的一致性问题,所以开发者应精准识别业务中可提升性能、有价值的字段进行反范式设计。

1.3 数据模型设计范式

综上所述,数据模型设计范式基本沿用关系型数据库范式:将表抽象为模型,将列抽象为字段,按照具体业务需求合理设置模型中的字段,系统已为每个模型固定内置了主键 “_id” 作为数据标识,开发者无需关心主键,只需要在模型中创建模型直接依赖的字段即可,适当增加冗余。

2. 数据模型创建与关联关系定义

接下来,我们以《学生信息管理系统》为需求背景,从数据库E-R设计延伸出数据模型设计,直到生产中如何使用模型操作数据。

说明:以下截图均来自云后台数据管理界面,点击阅读原文登录

2.1 业务模型 E-R 图

《学生信息管理系统》主要做学生相关数据管理,其中包含多对一、多对多和一对一关系,如下图所示:

2.2 创建模型

基于业务需求,我们整理成表格信息,首先我们先依次创建出每个模型单体,不考虑关联关系。说明:

  • 红色表示多对一关系
  • 绿色表示多对多关系
  • 黄色表示一对一关系
  • 关联关系方便展示,本小节先不关心,在下一小节使用

学生

班级

课程

学籍信息

姓名

名称

编号

编号

年龄

年级

名称

学籍所在地

性别

所在班级

班内学生

所学课程

选课学生

学籍档案

绑定学生

创建模型时,统一使用云后台-数据管理-从空白创建-云开发MySQL数据库

如果mysql数据库未初始化,可点击下方的初始化按钮,再继续操作

  • 创建学生模型

如果没有性别枚举,可以在创建时新建选项集

  • 创建班级模型
  • 创建课程模型
  • 创建学籍信息模型

2.3 创建关联关系

接下来我们来为模型建立关联关系,在云开发数据管理中关联关系是成对出现的,例如在学生和班级关系中(多对一关系),班级是学生的父模型(一方),那么学生就是班级的子模型(多方)。当我们成功为学生模型创建多对一关系关联班级模型后,班级模型中就会出现一对多关系关联学生模型。此时关联关系字段会自动关联目标模型的数据标识,即主键。

说明:

  1. 在编辑模式下,可以通过”添加一列“来继续创建关系字段
  2. 为了方便后续直观识别关系字段,我们将关系字段命名按照两个模型标识表示,如学生关联班级的字段是student_class,那么班级中成对的字段就是class_student,其他关系如是
  3. 在建立关系时,一定要分清当前主模型和关联模型的父子关系,从而选择对应字段类型
  • 创建学生-班级多对一关系
  • 创建学生-课程多对多关系
  • 创建学生-学籍一对一关系
  • 学生关联关系概览
  • 班级、课程、学籍中对应的关系

将所有的模型都创建完毕,物理层的数据库存储也伴随模型而创建,接下来对数据进行操作。

3. 数据模型的物理意义

数据模型是业务需求的抽象,属于逻辑层含义,但实际进行数据存储和处理的还是物理层的数据库,为了更形象的解释其对应关系,我们采用关系型数据库 SQL 作为参照说明。

以下给出的 SQL 仅为了解释映射关系,而非实际存储

  • 数据模型到物理存储

有同学肯定会问:既然模型字段和数据库列是一一对应的,为什么还需要数据模型,直接操作DB岂不更加直接明了?

  1. 首先,模型更容易理解更贴近自然语言,就好比面向对象语言之于汇编语言、 AIGC 之于人工智能、矿泉水之于冰山融雪...一一对应只是在当前业务场景下,更复杂的企业级模型可不一定哦
  2. 其次,模型更贴近业务的使用者而非底层逻辑的实现者,两者点亮的技能树不同
  3. 最后,模型身处逻辑层,屏蔽了来自物理层数据库的复杂设计和使用,最重要的是模型可以对接纷繁复杂眼花缭乱的各路数据库产品,云开发为广大开发者不仅提供了关系型数据库MySQL,还包括 NoSQL 数据库选项,都可以通过同一种模型接入
  • 关联关系物理意义
  1. 前文不断强调要识别多对一和一对多关系中的父子模型概念,在数据模型中,这两者关系都是通过子模型的关联字段来维护的。比如“学生-班级”是多对一关系,学生是子模型班级是父模型,那么关联关系值的物理存储位置一定是子模型学生的关联列student_class
  2. 从上图 SQL 可以看出,在多对多关系中,关联关系并不维护在某一方模型,而是会有中间模型来维护,该中间模型不具有业务属性,而仅仅作为多对多关系维系的纽带,所以它并不开放给开发者
  3. 一对一 关系是特殊的多对一(或一对多)关系,物理存储位置同后者

以上,我们只是对模型和物理存储做浅尝即止的解释,为求在模型设计和数据操作时有更直观的理解,接下来我们利用创建好的模型做实机数据演示。

4. 数据操作

4.1 创建数据

  • 通过控制台,依次创建班级、课程、学生数据,最后创建学籍数据并绑定学生信息
  • 如果使用sdk创建可参考下列方式,请点击使用文档 https://docs.cloudbase.net/model/introduce/
代码语言:javascript
复制
// 创建班级
const { data } = await models.class.createMany({
 data: [
  {
       name: "1班",  
       grade: "一年级"
  },
  {
       name: "2班",  
       grade: "一年级"
  }
],
});

// 创建课程
const { data } = await models.course.createMany({
 data: [
  {
       name: "语文",  
       code: "001"
  },
  {
       name: "数学",  
       code: "002"
  }
],
});

// 创建学籍信息
const { data } = await models.profile.createMany({
 data: [
  {
       code: "01",  
       address: "北京朝阳区"
  },
  {
       code: " 02",  
       address: "上海虹桥区"
  }
],
});

// 创建学生
const { data } = await models.student.createMany({
 data: [
  {
       "name": "小明",
       "birth": 6,
       "gender": "1",
       // 建立学籍一对一关系,_id为学籍数据标识
       "student_profile": {
           "_id": "9ZRF3VHQR6"
      },
       // 建立班级多对一关系,_id为班级数据标识
       "student_class": {
           "_id": "9ZREB4QKDS"
      },
       // 建立课程多对多关系,_id为课程数据标识
       "student_course": [
          {
               "_id": "9ZREE51ERE"
          },
          {
               "_id": "9ZREDFX4G8"
          }
      ]
  },
   
],
});
  • 为了方便在控制台查看,重新编辑模型,将学生姓名、班级名称、课程名称、学籍编号设置为“主展示列”。

我们创建好的两条学生数据如下:

姓名

年龄

性别

学籍档案

所在班级

所学课程

数据标识

小明

6

02

2班

语文、数学

9ZREQJ0MPW

小红

6

01

1班

语文、数学

9ZREUB0FJ0

4.2 数据查询

用如下几个场景介绍关联关系的查询。

  • 查询一年级 2 班所有的男生信息,包括班级、学籍和学习课程信息。
代码语言:javascript
复制
const { data } = await models.student.list({
// 展示参数,如果只展示当前模型非关联数据,可以使用 select:{$master:true}
       select: {
           _id: true,
           name: true,
           birth: true,
           gender: true,
           // 展示结果包含关联课程信息(多对多)
           student_course: {
               name: true,
               code: true
          },
           // 展示结果包含班级信息(多对一)
           student_class: {
               name: true,
               grade: true
          },
           // 展示结果包含学籍信息(一对一)
           student_profile: {
               code: true,
               name: true
          }
      },
       // 筛选条件,where指当前主模型条件;relateWhere指当前关联模型条件,其中relateWhere内的第一级参数为当前模型的关联字段,where内字段为关联模型字段
       filter: {
        // 条件:男生
           where: {
               $and: [
                  {
                       gender: {$eq: "1"}
                  }
              ]
          },
           // 条件:一年级 2 班
           relateWhere: {
               student_class:{ // 学生模型关联字段
                   where: {
                       $and:[
                          {
                               grade: {$eq: "一年级"}  // 班级模型字段
                          },
                          {
                               name: {$eq: "2班"}  // 班级模型字段
                          }
                      ]
                  }
              }
          }
      },
       pageSize: 10,   // 分页
       pageNumber: 1,  // 当前页数
       getCount: true  // 查询数据总数
  }
});
 

// 返回查询到的数据列表 records 和 总数 total
console.log(JSON.stringify((data)));

// return
//{  
// "records": [  
//   {  
//     "student_class": {"grade": "一年级","name": "2班","_id": "9ZREB4QKDS"},  
//     "gender": "1",  
//     "student_profile": {"code": " 02","_id": "9ZRF3VHQR6"},  
//     "name": "小明",  
//     "birth": 6,  
//     "_id": "9ZREQJ0MPW",  
//     "student_course": [  
//       {  
//         "code": "001",  
//         "name": "语文",  
//         "_id": "9ZREDFX4G8"  
//       },  
//       {  
//         "code": " 002",  
//         "name": "数学",  
//         "_id": "9ZREE51ERE"  
//       }  
//     ]  
//   }  
// ],  
// "total": 1  
//}

查询所有学生信息,按姓名字典序排序

代码语言:javascript
复制
const { data } = await models.student.list({
select: {
           $master:true  // 展示学生模型所有非关联字段
      },
       filter: {
           where: {}
      },
       orderBy:[
          {
               name: "DESC"
          }
      ],
       pageSize: 10,
       pageNumber: 1,
       getCount: true

});
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯云开发CloudBase 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1. 数据模型设计范式
    • 1.1 关系型数据库设计范式
      • 1.2 反范式设计
        • 1.3 数据模型设计范式
        • 2. 数据模型创建与关联关系定义
          • 2.1 业务模型 E-R 图
            • 2.2 创建模型
              • 2.3 创建关联关系
              • 4. 数据操作
                • 4.1 创建数据
                  • 4.2 数据查询
                  相关产品与服务
                  数据库
                  云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档