Gorm Preload

gorm 在使用Preload的时候, 在多对多模型下, 无法对中间表进行软删除判断

伪代码如下

 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

type User struct {
	ID     uint 
	UserID uint
	RoleID uint
	DeletedAt gorm.DeletedAt
	// any other field
    // code1
	Roles []Role `gorm:"->"`
	// code2
	UserRoles []UserRole `gorm:"->"`
}

type UserRole struct {
	ID     uint 
	UserID uint
	RoleID uint
	DeletedAt gorm.DeletedAt
	Role *Role
}

type Role struct {
	ID     uint 
	// any other field
}

func query() {
	var users []User
	// 这种情况下 无法对UserRole表进行软删除判断
	db.Model(User{}).Preload("Roles").Find(&users)
	
	// 解决方案1. 不使用软删除
	
	// 解决方案2. 两步Preload 不直接关联Role 实现如下
    // db.Model(User{}).Preload("UserRoles.Role").Find(&users)
}

解决方案1

中间表不使用软删除 实现如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type User struct {
	ID        uint
	UserID    uint
	RoleID    uint
	DeletedAt gorm.DeletedAt
	// any other field
	Roles []Role `gorm:"->"`
}

type UserRole struct {
	ID        uint
	UserID    uint
	RoleID    uint
}

type Role struct {
	ID uint
	// any other field
}

func query() {
	var users []User
	db.Model(User{}).Preload("Roles").Find(&users)
}

解决方案2

两步Preload 不直接关联Role 实现如下

 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
type User struct {
	ID        uint
	UserID    uint
	RoleID    uint
	DeletedAt gorm.DeletedAt
	// any other field
	// code2
	UserRoles []UserRole `gorm:"->"`
}

type UserRole struct {
	ID        uint
	UserID    uint
	RoleID    uint
	DeletedAt gorm.DeletedAt
	Role      *Role
}

type Role struct {
	ID uint
	// any other field
}

func query() {
	var users []User
	db.Model(User{}).Preload("UserRoles.Role").Find(&users)
}
updatedupdated2025-09-302025-09-30