uuid->学号

​ 在数据传输的过程中,一般不能使用真实的学号,或者姓名id,在数据库的存储过程中,一般也不是简单的ID自增形式,所以使用uuid和姓名或者学号的对应关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
type LibScore struct {
model.Base
Name string `gorm:"comment:指标名称"` // 2022-2023-1全校绩点
Tags datatypes.JSONSlice[string] `gorm:"comment:指标标签"`
Scope string `gorm:"comment:'指标等级: 系统级 system, 项目级 project/xxx'"`
Content []LibScoreContent `gorm:"foreignkey:LibScoreID;"`
}

type LibScoreContent struct {
model.Base
LibScoreID string `gorm:"size:26;index;comment:所属指标id"`
StaffId string `gorm:"size:19;comment:用户工号"`
Score string `gorm:"comment:指标内容分数/等级"`
Extra datatypes.JSON `gorm:"comment:额外信息"`
}

type Base struct {
ID string `json:"id" gorm:"primary_key;type:char(26)"`
CreatedAt time.Time `json:"-"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}

这是两张表,LibScore 和 LibScoreContent 一对多的对应关系

类似于 某个项目的成绩->许多人的成绩

我们需要实现查找 某个人的某个项目成绩,顺便返回其他项目的成绩

由于前端传回来的是 uuid ,因此不能获得真正的staffId,需要通过uuid来当桥梁。

因为外键,在LibScoreContent中的 LibScoreID 字段对应的是LibScore的主键(即model.base中的ID),而如何表示某个人呐,就是LibScoreContent中的model.Base.ID(称之为LibContentId)

总结一下就是 uuid = ContentId -> ContentId + scoreId -> staffId + scoreId = 某个人的项目信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
type LibScoreContentListByStaffIdResponse struct {
Total int64 `json:"total"`
Detail LibContentDetail `json:"list"`
Extra []LibContentDetail `json:"extra"`
}
// 其他有些dto的结构就不写了,反正就是传输
func HandleLibContentDetail(c flamego.Context, r flamego.Render, paginate page.Paginate) {
libScoreId := c.Param("id") // 某个项目信息
libContentId := c.Param("contentId") // 某个人的uuid获取
var libContentResponse dto.LibScoreContentListByStaffIdResponse
var libContent model.LibScoreContent
err := dao.Lib.Model(&model.LibScoreContent{}).WithContext(c.Request().Context()).
Where("lib_score_id = ? and id = ?", libScoreId, libContentId).
Find(&libContent).Error
if err != nil {
response.ServiceErr(r, err)
return
}
staffId := libContent.StaffId
var count int64
var relatedLibContent []model.LibScoreContent
err = dao.Lib.Model(&model.LibScoreContent{}).WithContext(c.Request().Context()).
Where("lib_score_id = ? and staff_id = ?", libScoreId, staffId).
Scopes(paginate.Paginate()).Find(&relatedLibContent).Offset(-1).Limit(-1).Count(&count).Error

if err != nil {
response.ServiceErr(r, err)
return
}
err = copier.Copy(&libContentResponse.Detail, &libContent)
if err != nil {
response.ServiceErr(r, err)
return
}
err = copier.Copy(&libContentResponse.Extra, &relatedLibContent)
if err != nil {
response.ServiceErr(r, err)
return
}
libContentResponse.Total = count
response.HTTPSuccess(r, libContentResponse)
}

如何制作uuid

使用Hook函数即可

1
2
3
4
func (u *User) BeforeCreate(*gorm.DB) error {
u.Id = ulid.Make().String()
return nil
}

这样子就能每个人都能有专属的ID了

[]string形式存储数据库

我们发现 []string形式的数据无法存入GORM数据库

用下面的形式来代替

1
Tags    datatypes.JSONSlice[string] `gorm:"comment:指标标签"`

外键和主键

主键

​ 是能确定一条记录的唯一标识,比如,一条记录包括身份正号,姓名,年龄。身份证号是唯一能确定你这个人的,其他都可能有重复,所以,身份证号是主键。

​ 实际上,主键除了惟一地标识一行之外,再没有其他的用途了

​ 主键应当有计算机自动生成。如果由人来对主键的创建进行干预,就会使它带有除了惟一标识一行以外的意义。

外键

主键和外键是把多个表组织为一个有效的关系数据库的粘合剂。

A表的外键往往B表的主键

在关系型数据库中,当一张表的外键与另一张表的字段引用其外键时,它们的值通常是相同的

但是上面的示例不一样,上面示例中直接把A表的主键和B建的随意字段相互关联了。