GoLong的学习之路(十九)基础工具之GORM(操作数据库)(关联)GORM中最重要的特点!(简化代码)

博客围绕GORM展开,介绍其在数据库操作中减少数据转换操作的方法。详细阐述了预加载,包括Joins预加载、嵌套预加载等多种方式,还讲解了Belongs To、Has one、Has Many、Many To Many等不同关联关系,涉及重写外键、引用及外键约束等内容。

上回书说到,CRUD的基本操作,这里就必须说一下。在正规的数据操作中,其实我们返还给后端返还给前端的数据,和前端所需要的数据是不一致。

就比如一个注册的操作。前端传给后端就包括但不限于。邮箱,密码,账号,姓名等,后端就会将这些保存起来,但是在登录的操作中只需要账号和密码。也就意味着我们需要经常进行数据的转换。

在GORM中有些方式可以减少我们的操作。

所以这回书就写,如何关联结构体数据库字段

预加载

什么是是预加载?
预加载其实就是在真正开始使用数据之前,先异步把数据加载好,等到需要使用时,就可以直接使用之前加载好的数据。

在GORM中其实就是通过预加载将联系进行加载建表。

type User struct {
   
   
  gorm.Model
  Username string
  Orders   []Order
}

type Order struct {
   
   
  gorm.Model
  UserID uint
  Price  float64
}

// 查找 user 时预加载相关 Order
db.Preload("Orders").Find(&users)
// SELECT * FROM users;
db.Preload("Orders").Preload("Profile").Preload("Role").Find(&users)
// SELECT * FROM users;
// SELECT * FROM orders WHERE user_id IN (1,2,3,4); // has many
// SELECT * FROM profiles WHERE user_id IN (1,2,3,4); // has one
// SELECT * FROM roles WHERE id IN (4,5,6); // belongs to

Joins预加载

Preload在单独的查询中加载关联数据,Join Preload将使用左连接加载关联数据。

db.Joins("Company", DB.Where(&Company{
   
   Alive: true})).Find(&users)
// SELECT `users`.`id`,`users`.`name`,`users`.`age`,`Company`.`id` AS `Company__id`,`Company`.`name` AS `Company__name` FROM `users` LEFT JOIN `companies` AS `Company` ON `users`.`company_id` = `Company`.`id` AND `Company`.`alive` = true;

联接嵌套模型

db.Joins("Manager").Joins("Manager.Company").Find(&users)
// SELECT "users"."id","users"."created_at","users"."updated_at","users"."deleted_at","users"."name","users"."age","users"."birthday","users"."company_id","users"."manager_id","users"."active","Manager"."id" AS "Manager__id","Manager"."created_at" AS "Manager__created_at","Manager"."updated_at" AS "Manager__updated_at","Manager"."deleted_at" AS "Manager__deleted_at","Manager"."name" AS "Manager__name","Manager"."age" AS "Manager__age","Manager"."birthday" AS "Manager__birthday","Manager"."company_id" AS "Manager__company_id","Manager"."manager_id" AS "Manager__manager_id","Manager"."active" AS "Manager__active","Manager__Company"."id" AS "Manager__Company__id","Manager__Company"."name" AS "Manager__Company__name" FROM "users" LEFT JOIN "users" "Manager" ON "users"."manager_id" = "Manager"."id" AND "Manager"."deleted_at" IS NULL LEFT JOIN "companies" "Manager__Company" ON "Manager"."company_id" = "Manager__Company"."id" WHERE "users"."deleted_at" IS NULL

预加载全部

clause.Associations关联可以像Select一样使用Preload,您可以使用它来预加载所有关联

type User struct {
   
   
  gorm.Model
  Name       string
  CompanyID  uint
  Company    Company
  Role       Role
  Orders     []Order
}

db.Preload(clause.Associations).Find(&users)

clause.Associations不会预加载嵌套关联,但可以将它与嵌套预加载一起使用

嵌套预加载

GORM支持嵌套预加载

db.Preload("Orders.OrderItems.Product").Preload("CreditCard").Find(&users)

// 自定义“订单”的预加载条件
// 并且GORM不会预加载不匹配的订单的OrderItems
db.Preload("Orders", "state = ?", "paid").Preload("Orders.OrderItems").Find(&users)

条件预加载

GORM允许预加载与条件关联,它的工作原理类似于内联条件。
带条件的预加载订单

db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
// SELECT * FROM users;
// SELECT * FROM orders WHERE user_id IN (1,2,3,4) AND state NOT IN ('cancelled');

db.Where("state = ?", "active").Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
// SELECT * FROM users WHERE state = 'active';
// SELECT * FROM orders WHERE user_id IN (1,2) AND state NOT IN ('cancelled');

自定义预加载SQL

可以通过传入func(db *gorm.DB) *gorm.DB来定制预加载SQL

db.Preload("Orders", func(db *gorm.DB) *gorm.DB {
   
   
  return db.Order("orders.amount DESC")
}).Find(&users)
// SELECT * FROM users;
// SELECT * FROM orders WHERE user_id IN (1,2,3,4) order by orders.amount DESC;

嵌入式预加载(嵌入式结构体)

嵌入式预加载用于嵌入式结构体,特别是同一结构体。嵌入式预加载的语法类似于嵌套预加载,它们由点划分。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值