ORM模型关联解析

2024-01-10 14:51:14

浏览:76

评论:0

什么是模型关联

模型关联是指在数据库中的两个或多个表之间建立关系,以便在查询和操作数据时能够方便地进行关联操作。模型关联主要用于ORM(对象关系映射)框架中,用于定义和处理数据库表之间的关系。 在使用ORM框架时,可以通过在模型类中定义关联关系来实现模型关联。这些关联关系通常使用关联方法(例如hasOne、hasMany、belongsTo等)来定义。

常见的模型关联有哪些

  • 一对一关联(One-to-One):一个模型实例与另一个模型实例之间存在唯一的关联关系。例如,一个用户(User)只有一个个人资料(Profile)。
  • 一对多关联(One-to-Many):一个模型实例与多个另一个模型实例之间存在关联关系。例如,一个作者(Author)可以有多篇文章(Article)。
  • 多对多关联(Many-to-Many):多个模型实例与多个另一个模型实例之间存在关联关系。例如,一个学生(Student)可以选择多门课程(Course),同时一门课程也可以有多个学生。
  • 多态关联(Polymorphic):一个模型实例可以与多个其他模型实例进行关联。例如,一个评论(Comment)可以关联到一篇文章(Article)或一张图片(Image)。

模型关联解析

一对一关联 常用hasOne定义。例如,一个用户(User)只有一个个人资料(Profile)

# 查询后生成的sql语句如下:
SELECT * FROM `vscing_user` WHERE `id` IN (1,2);
SELECT * FROM `vscing_profile` WHERE `user_id` = 1;
SELECT * FROM `vscing_profile` WHERE `user_id` = 2;
# 上述组合得出一个用户信息,并且获取到用户的个人资料信息,再经过ORM组装。但是存在着经典的N+1查询问题。

什么是N+1查询问题

  • N+1 查询问题指的是在关联查询中,对于每个主表记录,都会额外执行一次查询来获取关联表的数据,导致查询次数的增加,从而影响性能。
  • 在上述ORM框架中,使用一对一关联,会生成两条sql,当是循环查询时候,会生成N条个人资料查询,1条用户信息查询,合称N+1。
# 为了解决n+1,ORM框架又设计了关联预加载。一种是通过IN查询方式,一种是通过JOIN方式。
  
# IN查询方式生成的sql
SELECT * FROM `vscing_user` WHERE `id` IN (1,2);
SELECT * FROM `vscing_profile` WHERE `user_id` IN (1,2);

# JOIN查询方式生成的sql
SELECT
    `u`.`id`,
    `p`.`id` AS `profile_id` 
FROM
    `vscing_user` `u`
    INNER JOIN `vscing_profile` `p` ON `u`.`id` = `p`.`user_id` 
WHERE
    `u`.`id` IN ( 1, 2 );

# 上述组合得出一个用户信息,并且获取到用户的个人资料信息组装。并避免了N+1问题。

一对多关联 常用hasOne定义。例如,一个作者(Author)可以有多篇文章(Article)

# 关联预加载 查询生成的sql
SELECT * FROM `vscing_author` WHERE `id` IN (1,2);
SELECT * FROM `vscing_article` WHERE `user_id` IN (1,2);

# 上述组合得出一个作者信息并获取作者的多个文章

多对多关联(Many-to-Many):多个模型实例与多个另一个模型实例之间存在关联关系。例如,一个学生(Student)可以选择多门课程(Course),同时一门课程也可以有多个学生。

# 关联预加载 查询生成的sql
SELECT * FROM `vscing_student` WHERE `id` IN (1,2);
SELECT
    `c`.`*`
FROM
    `vscing_course` `c`
    INNER JOIN `vscing_student_has_course` `pivot` ON `c`.`id` = `pivot`.`course_id` 
WHERE
    `pivot`.`student_id` IN ( 1, 2 );

# 上述组合得出一个学生获取关联的多门课程,反之亦然一个课程获取关联的多个学生。

多态关联(Polymorphic):一个模型实例可以与多个其他模型实例进行关联。例如,一个评论(Comment)可以关联到一篇文章(Article)或一张图片(Image)。

## sql同上述一对一、一对多、多对多大体一致