Skip to content

Commit 18799bb

Browse files
committed
自定义实现的 driver.ValuerValue 方法,会被调用 3 次
1 parent fabf3ff commit 18799bb

File tree

3 files changed

+141
-51
lines changed

3 files changed

+141
-51
lines changed

Diff for: db.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func OpenTestConnection() (db *gorm.DB, err error) {
8383

8484
func RunMigrations() {
8585
var err error
86-
allModels := []interface{}{&User{}, &Account{}, &Pet{}, &Company{}, &Toy{}, &Language{}}
86+
allModels := []interface{}{&Model{}}
8787
rand.Seed(time.Now().UnixNano())
8888
rand.Shuffle(len(allModels), func(i, j int) { allModels[i], allModels[j] = allModels[j], allModels[i] })
8989

Diff for: main_test.go

+91-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,104 @@
11
package main
22

33
import (
4+
"context"
5+
"slices"
46
"testing"
57
)
68

79
// GORM_REPO: https://github.com/go-gorm/gorm.git
810
// GORM_BRANCH: master
911
// TEST_DRIVERS: sqlite, mysql, postgres, sqlserver
10-
1112
func TestGORM(t *testing.T) {
12-
user := User{Name: "jinzhu"}
13-
14-
DB.Create(&user)
13+
arrayInput := []string{"A", "B", "C"}
14+
arraySave := []string{"A1", "B1", "C1"}
1515

16-
var result User
17-
if err := DB.First(&result, user.ID).Error; err != nil {
18-
t.Errorf("Failed, got error: %v", err)
16+
data := Model{
17+
JsonField: JsonField{
18+
Array: slices.Clone(arrayInput),
19+
},
1920
}
21+
22+
t.Run("Create", func(t *testing.T) {
23+
err := DB.WithContext(context.TODO()).Model(&Model{}).
24+
Create(&data).
25+
Error
26+
if err != nil {
27+
t.Errorf("Failed, create error: %v", err)
28+
}
29+
30+
arrayCreate := data.JsonField.Array
31+
t.Logf("arrayCreate is %v", arrayCreate)
32+
if !slices.Equal(arrayCreate, arrayInput) {
33+
t.Errorf("Failed, json field arrayCreate %v not equal arrayInput %v", arrayCreate, arrayInput)
34+
}
35+
})
36+
37+
t.Run("Find With SkipCustomMethod", func(t *testing.T) {
38+
var modelSkip *ModelSkip
39+
err := DB.WithContext(context.TODO()).Model(&Model{}).
40+
Where("id", data.ID).
41+
Find(&modelSkip).
42+
Error
43+
if err != nil {
44+
t.Errorf("Failed, get error: %v", err)
45+
}
46+
47+
arraySkip := modelSkip.JsonField.Array
48+
t.Logf("arraySkip is %v", arraySkip)
49+
if !slices.Equal(arraySkip, arraySave) {
50+
t.Errorf("Failed, modelSkip field arraySkip %v not equal arraySave %v", arraySkip, arraySave)
51+
}
52+
})
53+
54+
t.Run("Find", func(t *testing.T) {
55+
var row *Model
56+
err := DB.WithContext(context.TODO()).Model(&Model{}).
57+
Where("id", data.ID).
58+
Find(&row).
59+
Error
60+
if err != nil {
61+
t.Errorf("Failed, find error: %v", err)
62+
}
63+
64+
arrayFind := row.JsonField.Array
65+
t.Logf("arrayFind is %v", arrayFind)
66+
if !slices.Equal(arrayFind, arrayInput) {
67+
t.Errorf("Failed, json field arrayFind %v not equal arrayInput %v", arrayFind, arrayInput)
68+
}
69+
})
70+
71+
t.Run("Update", func(t *testing.T) {
72+
arrayUpdate := []string{"X", "Y", "Z"}
73+
arrayUpdateSave := []string{"X1", "Y1", "Z1"}
74+
75+
err := DB.WithContext(context.TODO()).Model(&Model{}).
76+
Where("id", data.ID).
77+
Updates(Model{
78+
JsonField: JsonField{
79+
Array: slices.Clone(arrayUpdate),
80+
},
81+
}).
82+
Error
83+
if err != nil {
84+
t.Errorf("Failed, update error: %v", err)
85+
}
86+
87+
t.Run("ModelSkip", func(t *testing.T) {
88+
var modelSkip *ModelSkip
89+
err = DB.WithContext(context.TODO()).Model(&Model{}).
90+
Where("id", data.ID).
91+
Find(&modelSkip).Error
92+
if err != nil {
93+
t.Errorf("Failed, get error: %v", err)
94+
}
95+
96+
arraySkip := modelSkip.JsonField.Array
97+
t.Logf("arraySkip is %v", arraySkip)
98+
if !slices.Equal(arraySkip, arrayUpdateSave) {
99+
t.Errorf("Failed, json field %v arrayInput not equal arrayUpdateSave %v", arraySkip, arrayUpdateSave)
100+
}
101+
})
102+
})
103+
20104
}

Diff for: models.go

+49-43
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,66 @@
11
package main
22

33
import (
4-
"database/sql"
5-
"time"
4+
"database/sql/driver"
5+
"encoding/json"
6+
"fmt"
7+
"slices"
8+
"strings"
69

710
"gorm.io/gorm"
811
)
912

10-
// User has one `Account` (has one), many `Pets` (has many) and `Toys` (has many - polymorphic)
11-
// He works in a Company (belongs to), he has a Manager (belongs to - single-table), and also managed a Team (has many - single-table)
12-
// He speaks many languages (many to many) and has many friends (many to many - single-table)
13-
// His pet also has one Toy (has one - polymorphic)
14-
type User struct {
13+
type Model struct {
1514
gorm.Model
16-
Name string
17-
Age uint
18-
Birthday *time.Time
19-
Account Account
20-
Pets []*Pet
21-
Toys []Toy `gorm:"polymorphic:Owner"`
22-
CompanyID *int
23-
Company Company
24-
ManagerID *uint
25-
Manager *User
26-
Team []User `gorm:"foreignkey:ManagerID"`
27-
Languages []Language `gorm:"many2many:UserSpeak"`
28-
Friends []*User `gorm:"many2many:user_friends"`
29-
Active bool
30-
}
31-
32-
type Account struct {
33-
gorm.Model
34-
UserID sql.NullInt64
35-
Number string
15+
JsonField JsonField `gorm:"type:json;not null;" json:"jsonField"`
3616
}
3717

38-
type Pet struct {
39-
gorm.Model
40-
UserID *uint
41-
Name string
42-
Toy Toy `gorm:"polymorphic:Owner;"`
18+
type JsonField struct {
19+
Array []string `json:"array"`
4320
}
4421

45-
type Toy struct {
46-
gorm.Model
47-
Name string
48-
OwnerID string
49-
OwnerType string
22+
func (j *JsonField) Scan(src any) error {
23+
err := json.Unmarshal(src.([]byte), &j)
24+
if err != nil {
25+
return fmt.Errorf("json scan fail, err: %w", err)
26+
}
27+
28+
for i, s := range j.Array {
29+
j.Array[i], _ = strings.CutSuffix(s, "1")
30+
}
31+
32+
return nil
33+
}
34+
35+
func (j JsonField) Value() (driver.Value, error) {
36+
clone := slices.Clone(j.Array)
37+
for i := range clone {
38+
clone[i] += "1" // 我想要修改(加密)原来的字段,I want to modify/encrypt the fields
39+
}
40+
41+
data, err := json.Marshal(JsonField{
42+
Array: clone,
43+
})
44+
if err != nil {
45+
return nil, fmt.Errorf("json marshal fail, err: %w", err)
46+
}
47+
48+
return data, nil
49+
}
50+
51+
type SkipCustomMethod struct {
52+
Array []string `gorm:"type:json;not null;" json:"array"`
53+
}
54+
55+
func (s *SkipCustomMethod) Scan(src any) error {
56+
return json.Unmarshal(src.([]byte), &s)
5057
}
5158

52-
type Company struct {
53-
ID int
54-
Name string
59+
func (s SkipCustomMethod) Value() (driver.Value, error) {
60+
return json.Marshal(s)
5561
}
5662

57-
type Language struct {
58-
Code string `gorm:"primarykey"`
59-
Name string
63+
// ModelSkip to skip JsonField.Value and JsonField.Scan
64+
type ModelSkip struct {
65+
JsonField SkipCustomMethod `json:"jsonField"`
6066
}

0 commit comments

Comments
 (0)