【Sequelize】关联模型和孤儿记录

news2025/4/16 13:47:34

一、关联模型的核心机制

1. 关联类型与组合规则

基础四类型
hasOne:外键存储于目标模型(如用户档案表存储用户ID)
belongsTo:外键存储于源模型(如订单表存储用户ID)
hasMany:一对多关系,外键在目标模型(如用户有多篇文章)
belongsToMany:通过中间表实现多对多(如用户-角色中间表)

必须成对定义
• 单边定义会导致预加载失效。例如仅定义Foo.hasOne(Bar)时,无法通过Bar.findAll({ include: Foo })查询
• 正确组合方式:

 // 一对一
 User.hasOne(Profile);
 Profile.belongsTo(User);

 // 一对多
 User.hasMany(Post);
 Post.belongsTo(User);

 // 多对多
 User.belongsToMany(Role, { through: UserRole });
 Role.belongsToMany(User, { through: UserRole });

有关联字段的表,一定是属于 belongsTo 其他表的。

2. 高级关联配置

自定义外键与别名

User.hasMany(Comment, {
  foreignKey: 'authorId',  // 覆盖默认的userId
  as: 'reviews'           // 通过user.getReviews()访问
});

当模型名称复数形式异常时(如Person→People),需通过as别名修正方法名

非主键关联

Ship.belongsTo(Captain, {
  targetKey: 'name',  // 关联船长表的name字段(需唯一约束)
  foreignKey: 'captainName'
});

需确保目标字段有唯一索引,否则会报错

3. 实际应用

在模型定义的时候关联模型:

在这里插入图片描述

然后再进行查询的第三个配置参数中定义 condition,来对查询结果进行关联:

在这里插入图片描述


二、孤儿记录的防护策略

孤儿记录:比如一个分类中关联了多个课程,此时将这个分类删掉,那么课程将找不到父记录,因此就成为了孤儿记录。

解决这个问题有三个方法:

  1. 设置外键约束(一般不用,在数据量大、高并发的场景下,会出现性能瓶颈)
  2. 删除分类的同时,删除该分类下的所有课程(代码层面,问题是可能发生误删除操作)
  3. 只有当没有关联该分类的课程时,才能被删掉(代码层面,推荐)
1. 外键约束级联

在定义关联时启用数据库级联删除,确保父记录删除时自动清理子记录:

// 用户删除时级联删除文章
User.hasMany(Post, {
  foreignKey: { allowNull: false }, // 强制外键非空
  onDelete: 'CASCADE' // 关键配置
});

此配置会在SQL层面生成ON DELETE CASCADE约束,彻底避免孤儿记录

2. 中间表清理(多对多关系)

使用钩子函数清理关联记录:

// 删除教师前清理关联表
Teacher.beforeDestroy(async (teacher) => {
  await Relation.destroy({
    where: { teacherId: teacher.id }
  });
});

特别适用于多对多关系中间表的数据维护

3. 事务保护

关键操作使用事务保证原子性:

await sequelize.transaction(async (t) => {
  const user = await User.findByPk(1, { transaction: t });
  await user.destroy({ transaction: t });
  // 自动触发关联的级联删除
});

防止在删除过程中断导致数据不一致


三、最佳实践建议

  1. 索引优化
    • 所有外键字段必须建立索引
    • 多对多中间表的联合索引:

    Relation.init({
      studentId: { type: INTEGER, primaryKey: true },
      teacherId: { type: INTEGER, primaryKey: true }
    }, { sequelize });
    

    通过复合主键提升查询效率

  2. 数据验证

    Post.belongsTo(User, {
      foreignKey: {
        validate: {
          isUserIdValid(value) {
            if (!validator.isUUID(value)) throw new Error('非法用户ID');
          }
        }
      }
    });
    
  3. 预加载优化

    User.findAll({
      include: [{
        model: Post,
        attributes: ['id', 'title'], // 按需加载字段
        where: { status: 'published' } // 过滤条件
      }]
    });
    

    避免N+1查询问题


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2335998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Sentinel实战教程:流量控制与Spring Boot集成

Sentinel实战教程:流量控制与Spring Boot集成 1. Sentinel简介与核心概念 1.1 什么是Sentinel? Sentinel是阿里巴巴开源的流量控制组件,主要用于微服务架构中的流量防护。它通过限流、熔断、热点防护等机制,帮助系统在高并发场景下保持稳定运行。 1.2 核心功能与术语 流…

循环神经网络 - 扩展到图结构之递归神经网络

本文我们来学习递归神经网络(Recursive Neural Network,RecNN),其是循环神经网络在有向无循环图上的扩展 。 递归神经网络是一类专门设计来处理具有层次结构或树形结构的数据的神经网络模型。它与更常见的循环神经网络(Recurrent Neural Net…

Maven超级详细安装部署

1.到底什么是Maven?搞清楚这个 Maven 是一个项目管理工具,主要用于 Java 项目的构建、依赖管理和文档生成。 它基于项目对象模型(POM),通过 pom.xml 文件定义项目的配置。 (简单说破:就是工程…

电机控制-隆博戈观测器(Luenberger state observer)

本文围绕基于无传感器控制策略的状态观测器展开,介绍其在电机领域的应用、原理、性能表现及无传感器驱动的优劣: 应用场景:适用于燃油泵、风扇等大量固定转速和低成本应用场景。工作原理:状态观测器利用完整的电机微分模型&#…

RK3506+net9+VS2022跨平台调试C#程序

下载GetVsDbg.sh ,这脚本会下载一个压缩包,然后解压缩,设置x权限等等。但是目标板子连不上,就想办法获取到下载路径,修改这个脚本,显示这个下载链接后,复制一下,用电脑下下来 修改好…

【16】数据结构之基于树的排序算法篇章

目录标题 选择排序简单选择排序树形选择排序 堆排序堆的定义Heap小跟堆大根堆堆的存储堆的代码设计堆排序的代码设计 排序算法综合比较 选择排序 基本思想:从待排序的序列中选出最大值或最小值,交换该元素与待排序序列的头部元素,对剩下的元…

华熙生物亮相消博会,这次又带来了什么样的变化?

首先,从展示层面来看,华熙生物在消博会上构建科技桥梁,展台主视觉展示糖生物学发展历程与自身发展交织历程,这象征着中国生物科技企业从产业突围到定义全球标准的蜕变。这一展示不仅提升了华熙生物的品牌形象,更向外界…

大象机器人推出myCobot 280 RDK X5,携手地瓜机器人共建智能教育机

摘要 大象机器人全新推出轻量级高性能教育机械臂 myCobot 280 RDK X5,该产品集成地瓜机器人 RDK X5 开发者套件,深度整合双方在硬件研发与智能计算领域的技术优势,实现芯片架构、软件算法、硬件结构的全栈自主研发。作为国内教育机器人生态合…

【初阶数据结构】——算法复杂度

一、前言 1、数据结构是什么? 数据结构(Data Structure)是计算机存储、组织数据的⽅式,指相互之间存在⼀种或多种特定关系的数 据元素的集合。没有⼀种单⼀的数据结构对所有⽤途都有⽤,所以我们要学各式各样的数据结构, 如&…

Google-A2A协议全面解析:一文掌握Agent-to-Agent协议的核心与应用

前言: 在当今人工智能技术飞速发展的时代,智能体(Agent)已悄然融入我们生活的各个角落。无论是个人智能助手,还是企业的自动化工具,各类AI代理的应用愈发广泛。但目前这些智能体之间大多处于孤立状态&…

Linux-服务器添加审计日志功能

#查看audit软件是否在运行(状态为active而且为绿色表示已经在运行) systemctl start auditd #如果没有在运行的话,查看是否被系统禁用 (audit为0表示被禁用) cat /proc/cmdline | grep -w "audit=0" #修改/etc/default/grub里面audit=0 改为audit=1 #更新GRUB…

基于机器视觉的多孔零件边缘缺陷检测(源码C++、opencv、凸包、凸缺陷检测)

👑主页:吾名招财 👓简介:工科学硕,研究方向机器视觉,爱好较广泛… ​💫签名:面朝大海,春暖花开! 基于机器视觉的多孔零件边缘缺陷检测(源码C、ope…

如何使用AI辅助开发CSS3 - 通义灵码功能全解析

一、引言 CSS3 作为最新的 CSS 标准,引入了众多新特性,如弹性布局、网格布局等,极大地丰富了网页样式的设计能力。然而,CSS3 的样式规则繁多,记忆所有规则对于开发者来说几乎是不可能的任务。在实际开发中&#xff0c…

MySQL入门:数据表的创建

​今天我们来介绍一下除HTML外的另一种语言:MySQL语言; MySQL:即一种用于管理和处理关系数据库的标准语言。要用于执行查询、更新、管理数据库中的数据以及定义和操作数据库结构。 接下来我会逐一介绍它的作用以及其中数据表,数据…

数据库的基本原则

数据库的核心原则 原子性与持久性:原子性(Atomicity)确保一个事务中的所有操作要么全部完成,要么完全不执行,不会出现部分完成的情况。持久性(Durability)则保证一旦事务提交成功,即…

Rust 中的Relaxed 内存指令重排演示:X=0 Y=0 是怎么出现的?

🔥 Rust 中的内存重排演示:X0 && Y0 是怎么出现的? 在并发编程中,我们经常会听说“内存重排(Memory Reordering)”这个术语,但它似乎总是只出现在理论或者别人口中的幻觉里。本文将通过…

C++进程间通信开发实战:高效解决项目中的IPC问题

C进程间通信开发实战:高效解决项目中的IPC问题 在复杂的软件项目中,进程间通信(Inter-Process Communication, IPC)是实现模块化、提高系统性能与可靠性的关键技术之一。C作为一门高性能的编程语言,广泛应用于需要高效…

FPGA-DDS技术的波形发生器

1.实验目的 1.1掌握直接数字频率合成(DDS)的基本原理及其实现方法。 1.2在DE2-115 FPGA开发板上设计一个可调频率的正弦波和方波发生器,频率范围10Hz~5MHz,最小分辨率小于1kHz。 1.3使用Quartus II进行仿真,并通过S…

C#实现通过MQTT Broker——EMQX发布订阅消息及其认证、授权的安全配置操作

一、准备内容 MQTT的构成、使用场景、工作原理介绍-CSDN博客文章浏览阅读656次,点赞7次,收藏12次。MQTT(Message Queuing Telemetry Transport)是一种轻量级、基于发布-订阅模式的消息传输协议【适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境】它在物联网应用中…

【双指针】三数之和(medium)

三数之和(medium) 题⽬描述:解法(排序双指针):算法思路:C 算法代码:Java 算法代码:注:数组转列表 题⽬链接:15. 三数之和 题⽬描述: …