1 基本使用
1.1 连接数据库
func BasicUsage() {
dsn := "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
fmt.Println(db)
}
1.2 基于模型迁移表结构
type Article struct {
gorm.Model
Subject string
Likes uint
Published bool
PublishTime time.Time
AuthorID uint
}
func BasicUsage() {
dsn := "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
if err := db.AutoMigrate(&Article{}); err != nil {
log.Fatal(err)
}
}
1.3 基本的crud
var DB *gorm.DB
func init() {
const dsn = "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
if err := db.AutoMigrate(&Article{}); err != nil {
log.Fatal(err)
}
DB = db
}
func Create() {
article := &Article{
Subject: "gorm 增操作",
Likes: 0,
Published: true,
PublishTime: time.Time{},
AuthorID: 2,
}
if err := DB.Create(article).Error; err != nil {
log.Fatal(err)
}
fmt.Println(article)
}
func Retrieve(id uint) {
article := &Article{}
if err := DB.First(article, id).Error; err != nil {
log.Fatal(err)
}
fmt.Println(article)
}
func Update() {
article := &Article{}
if err := DB.First(article, 1).Error; err != nil {
log.Fatal(err)
}
article.AuthorID = 23
article.Likes = 512
article.Subject = "新的文章标题"
if err := DB.Save(article).Error; err != nil {
log.Fatal(err)
}
}
func Delete() {
article := &Article{}
if err := DB.First(article, 2).Error; err != nil {
log.Fatal(err)
}
if err := DB.Delete(article).Error; err != nil {
log.Fatal(err)
}
}
1.4 debug 日志
func Debug() {
article := &Article{
Subject: "这是一条新插入的数据",
AuthorID: 50,
}
if err := DB.Create(article).Error; err != nil {
log.Fatal(err)
}
if err := DB.Debug().First(article, article.ID).Error; err != nil {
log.Fatal(err)
}
}
var logWriter io.Writer
logWriter, _ = os.OpenFile("./sql.log", os.O_CREATE|os.O_APPEND, 0644)
customLogger := logger.New(log.New(logWriter, "\n", log.LstdFlags),
logger.Config{
SlowThreshold: 200 * time.Millisecond,
LogLevel: logger.Info,
IgnoreRecordNotFoundError: false,
Colorful: false,
})
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: customLogger,
})
2 模型定义
2.1 表名定义
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: customLogger,
NamingStrategy: schema.NamingStrategy{
TablePrefix: "msb_",
SingularTable: true,
NameReplacer: nil,
NoLowerCase: false,
},
})
if err != nil {
log.Fatal(err)
}
func Migrate() {
if err := DB.AutoMigrate(&Post{}, &Category{}, &PostCategory{}, &Box{}); err != nil {
log.Fatal(err)
}
}
2.2 字段类型映射
2.3 指针类型与非指针类型区别
- 若表中字段不为null,则使用T类型就够了 因为不存在例如(数据库中为null,对应到结构体中值为0,则0到底是不是有用的值)
2.4 自定义字段类型
type CustomTypeModel struct {
gorm.Model
FTime time.Time
FNullTime sql.NullTime
Fstring string
FNullString sql.NullString
FUUID uuid.UUID
FNullUUID uuid.NullUUID
}
func CustomType() {
ctm := &CustomTypeModel{}
DB.AutoMigrate(ctm)
ctm.FTime = time.Time{}
ctm.FNullTime = sql.NullTime{}
ctm.Fstring = ""
ctm.FNullString = sql.NullString{}
ctm.FUUID = uuid.New()
ctm.FNullUUID = uuid.NullUUID{}
DB.Create(ctm)
DB.First(ctm, ctm.ID)
if ctm.Fstring == "" {
fmt.Println("FString is NULL")
} else {
fmt.Println("FString is NOT NULL")
}
if ctm.FNullString.Valid == false {
fmt.Println("FNullString is NULL")
} else {
fmt.Println("FNullString is NOT NULL")
}
}
2.5 字段标签设置字段属性
type FieldTag struct {
gorm.Model
FStringDefault string `gorm:`
FTypeChar string `gorm:"type:char(32)"`
FTypeVarchar string `gorm:"type:varchar(255)"`
FTypeText string `gorm:"type:text"`
FTypeBlob []string `gorm:"type:blob"`
FTypeEnum string `gorm:"type:enum('GO','GORM','MySQL')"`
FTypeSet string `gorm:"type:set('GO','GORM','MySQL')"`
FColNum string `gorm:"column:cus tom_column_name"`
FColNotNull string `gorm:"type:varchar(255);not null"`
FColDefault string `gorm:"type:varchar(255);default: gorm middle ware;"`
FColComment string `gorm:"type:varchar(255);comment:带有注释的字段"`
}
2.6 索引和约束管理
type IAndC struct {
ID uint `gorm:"primaryKey"`
Email string `gorm:"type:varchar(255);uniqueIndex"`
Age uint8 `gorm:"index;check:age >= 18 AND email is not null"`
FirstName string `gorm:"index:name"`
LastName string `gorm:"index:name"`
FirstName1 string `gorm:"index:name1,priority:2"`
LastName1 string `gorm:"index:name,priority:1"`
Height float32 `gorm:"index:,sort:desc"`
AddressHash string `gorm:"index:,length:12,comment:前12个字符作为索引关键字"`
}
2.7 字段操作控制
type Service struct {
gorm.Model
Url string `gorm:"-:migration"`
Schema string
Host string
Path string
QueryString string
}
2.8 序列化器的使用
type Paper struct {
gorm.Model
Subject string
Tags []string `gorm:"serializer:json"`
}
func PaperCrud() {
err := DB.AutoMigrate(&Paper{})
if err != nil {
log.Fatal(err)
}
paper := &Paper{}
paper.Subject = "使用serializer操作Tags字段"
paper.Tags = []string{"GO", "Serializer", "Gorm", "MySQL"}
if err := DB.Create(paper).Error; err != nil {
log.Fatal(err)
}
newPaper := &Paper{}
DB.First(newPaper, 2)
fmt.Printf("%+v", newPaper)
}
2.9 自定义序列化器的实现
type Paper struct {
gorm.Model
Subject string
Tags []string `gorm:"serializer:json"`
Categories []string `gorm:"serializer:csv"`
}
type CSVSerializer struct{}
func (CSVSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) error {
var fieldValue []string
if dbValue != nil {
var str string
switch v := dbValue.(type) {
case string:
str = v
case []byte:
str = string(v)
default:
return fmt.Errorf("failed to unmarshal CSV value :%#v", dbValue)
}
fieldValue = strings.Split(str, ",")
}
field.ReflectValueOf(ctx, dst).Set(reflect.ValueOf(fieldValue))
return nil
}
func (CSVSerializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
return strings.Join(fieldValue.([]string), ","), nil
}
func CustomSerializer() {
schema.RegisterSerializer("csv", CSVSerializer{})
err := DB.AutoMigrate(&Paper{})
if err != nil {
log.Fatal(err)
}
paper := &Paper{}
paper.Subject = "使用自定义操作categories字段"
paper.Categories = []string{"GO", "Serializer", "Gorm", "MySQL", "categories "}
paper.Tags = []string{"GO", "Serializer", "Gorm", "MySQL"}
if err := DB.Create(paper).Error; err != nil {
log.Fatal(err)
}
newPaper := &Paper{}
DB.First(newPaper, paper.ID)
fmt.Printf("%+v", newPaper)
}
2.10 嵌入结构体和gorm.model
type Blog struct {
gorm.Model
BlogBasic
Author `gorm:"embeddedPrefix:au thor_"`
}
type BlogBasic struct {
Subject string
Summary string
Content string
}
type Author struct {
Name string
Email string
}
2.10 小节
3 具体操作
3.1
3.2 错误处理
3.3 基于模型和map完成创建
type Content struct {
gorm.Model
Subject string
Likes uint
PublishTime *time.Time
}
func CreateBasic() {
DB.AutoMigrate(&Content{})
c1 := Content{}
c1.Subject = "GORM的使用"
result := DB.Create(&c1)
if result.Error != nil {
log.Fatal(result.Error)
}
fmt.Println(c1.ID, result.RowsAffected)
values := map[string]any{
"Subject": "通过map指定的值",
"PublishTime": time.Now(),
}
result2 := DB.Model(&Content{}).Create(values)
if result2.Error != nil {
log.Fatal(result2.Error)
}
fmt.Println(result2.RowsAffected)
}
- 使用map 自动更新创建时间 不会随之添加,只会在记录中添加map中有的数据
3.4 批量插入
func CreateMulti() {
DB.AutoMigrate(&Content{})
models := []Content{
{Subject: "标题1"},
{Subject: "标题2"},
{Subject: "标题3"},
{Subject: "标题3-1"},
}
result := DB.Create(&models)
if result.Error != nil {
log.Fatal(result.Error)
}
fmt.Println("RowsAffected:", result.RowsAffected)
for _, m := range models {
fmt.Println("ID:", m.ID)
}
vs := []map[string]any{
{"Subject": "标题4"},
{"Subject": "标题5"},
{"Subject": "标题6"},
{"Subject": "标题6-1"},
}
result2 := DB.Model(&Content{}).Create(vs)
if result2.Error != nil {
log.Fatal(result2.Error)
}
fmt.Println("ROWS:", result2.RowsAffected)
}}
func CreateBatches() {
DB.AutoMigrate(&Content{})
models := []Content{
{Subject: "标题11"},
{Subject: "标题12"},
{Subject: "标题13"},
{Subject: "标题14"},
}
result := DB.CreateInBatches(&models, 2)
if result.Error != nil {
log.Fatal(result.Error)
}
fmt.Println("RowsAffected:", result.RowsAffected)
for _, m := range models {
fmt.Println("ID:", m.ID)
}
vs := []map[string]any{
{"Subject": "标题15"},
{"Subject": "标题16"},
{"Subject": "标题17"},
{"Subject": "标题18"},
}
result2 := DB.Model(&Content{}).CreateInBatches(vs, 2)
if result2.Error != nil {
log.Fatal(result2.Error)
}
fmt.Println("ROWS:", result2.RowsAffected)
}
3.5 UpSert更新插入
func UpSert() {
DB.AutoMigrate(&Content{})
c1 := Content{}
c1.Subject = "新标题1111"
c1.Likes = 10
DB.Create(&c1)
c2 := Content{}
c2.ID = c1.ID
c2.Subject = "新标题*****"
c2.Likes = 200
DB.Create(&c1)
fmt.Println(c1)
if err := DB.
Clauses(clause.OnConflict{UpdateAll: true}).
Create(&c2).Error; err != nil {
log.Fatal(err)
}
c4 := Content{}
c4.ID = c1.ID
c4.Subject = "新标题456789"
c4.Likes = 300
if err := DB.Clauses(clause.OnConflict{DoUpdates: clause.AssignmentColumns(
[]string{"likes"})}).
Create(&c4).
Error; err != nil {
log.Fatal(err)
}
}
3.6 创建时默认值的处理
type Content struct {
gorm.Model
Subject string
Likes uint `gorm:"default:99"`
Vikes *uint `gorm:"default:99"`
PublishTime *time.Time
}
func DefaultValue() {
DB.AutoMigrate(&Content{})
c1 := Content{}
c1.Subject = "新标题2222"
vlikes := uint(0)
c1.Vikes = &vlikes
DB.Create(&c1)
}
3.7 创建时选择特定字段
func Omit() {
DB.AutoMigrate(&Content{})
c1 := Content{}
c1.Subject = "原始标题"
c1.Likes = 10
c1.Vikes = 99
now := time.Now()
c1.PublishTime = &now
DB.Select("Subject", "Likes", "UpdatedAt").Create(&c1)
DB.Omit("Subject", "UpdatedAt", "Vikes").Create(&c1)
}
3.8 创建时的钩子方法
func (c *Content) BeforeCreate(db *gorm.DB) error {
if c.PublishTime == nil {
now := time.Now()
c.PublishTime = &now
}
db.Statement.AddClause(clause.OnConflict{UpdateAll: true})
return nil
}
3.9 查询 基于主键的查询
type Content struct {
gorm.Model
Subject string
Likes uint `gorm:`
Vikes uint `gorm:`
PublishTime *time.Time
}
type ContentStrPK struct {
ID string `gorm:"primaryKey"`
Subject string
Likes uint
Views uint
PublishTime *time.Time
}
func GetByPk() {
DB.AutoMigrate(&Content{}, &ContentStrPK{})
c := Content{}
if err := DB.First(&c, 10).Error; err != nil {
log.Println(err)
}
cStr := ContentStrPK{}
if err := DB.First(&cStr, "id = ?", "some pk").Error; err != nil {
log.Println(err)
}
var cs []Content
if err := DB.Find(&cs, []uint{10, 11, 12, 13}).Error; err != nil {
log.Println(err)
}
for _, v := range cs {
fmt.Println(v)
}
var cStrs []ContentStrPK
if err := DB.Find(&cStrs, "id IN ?", []string{"some", "key", "you"}).Error; err != nil {
log.Println(err)
}
}
3.10 查询单条
func GetONE() {
c := Content{}
if err := DB.First(&c, "id > ?", 19).Error; err != nil {
log.Println(err)
}
fmt.Println("first ", c)
l := Content{}
if err := DB.Last(&l, "id > ?", 19).Error; err != nil {
log.Println(err)
}
fmt.Println("Last ", l)
t := Content{}
if err := DB.Take(&t, "id > ?", 19).Error; err != nil {
log.Println(err)
}
fmt.Println("Take ", t)
f := Content{}
if err := DB.Limit(1).Find(&f, "id > ?", 19).Error; err != nil {
fmt.Println(err)
}
fmt.Println("Limit Find ", f)
fs := Content{}
if err := DB.Find(&fs, "id > ?", 19).Error; err != nil {
fmt.Println(err)
}
fmt.Println("find ", fs)
}
3.11 查询结果扫描到Map类型
func GetToMap() {
c := map[string]any{}
if err := DB.Model(&Content{}).First(&c, 13).Error; err != nil {
log.Println(err)
}
fmt.Println(c["id"])
if c["id"].(uint) == 13 {
fmt.Println("BING GO!")
}
fmt.Println(c["created_at"])
t, err := time.Parse("2006-01-02 15:04:05.000 -0700 CST", "2023-08-24 20:46:20.372 +0800 CST")
if err != nil {
log.Println(err)
}
if c["created_at"].(time.Time) == t {
fmt.Println("created_at time bingo !")
}
var cs []map[string]any
if err := DB.Model(&Content{}).Find(&cs, []uint{18, 19, 20}).Error; err != nil {
fmt.Println(err)
}
for _, v := range cs {
fmt.Println(v["id"], v["subject"])
}
}
3.12 查询单列
func GetPluck() {
var subjects []sql.NullString
if err := DB.Model(Content{}).Pluck("subject", &subjects).Error; err != nil {
fmt.Println(err)
}
for _, v := range subjects {
if v.Valid {
fmt.Println(v.String)
} else if v.Valid == false {
fmt.Println("{NULL}", v.Valid)
}
}
}
func GetPluckExp() {
var subjects []string
if err := DB.Model(&Content{}).
Pluck("concat(coalesce(subject,'[no subject]'),'-',likes)", &subjects).Error; err != nil {
log.Println(err)
}
for _, v := range subjects {
fmt.Println(v)
}
}
3.13 字段选择子句
type Content struct {
gorm.Model
Subject string
Likes uint `gorm:`
Vikes uint `gorm:`
PublishTime *time.Time
Sv string `gorm:"-:migration;<-:false;"`
}
func GetSelect() {
var c Content
var cm map[string]any
if err := DB.Select("subject", "likes").First(&c, 13).Error; err != nil {
log.Fatalln(err)
}
if err := DB.Select("subject", "likes", "concat(subject,'-',vikes) AS sv").First(&c, 13).Error; err != nil {
log.Fatalln(err)
}
if err := DB.Model(&Content{}).Select("subject", "likes", "concat(subject,'-',vikes) AS sv").First(&cm, 13).Error; err != nil {
log.Fatalln(err)
}
fmt.Printf("%+v\n", cm)
}
3.14 去重选项distinct
func GetDistinct() {
var cs []Content
if err := DB.Distinct("subject").Find(&cs).Error; err != nil {
log.Fatalln(err)
}
for _, v := range cs {
fmt.Printf("%+v\n", v.Subject)
}
}
3.15 条件设置方法
func WhereMethod() {
var cs []Content
if err := DB.Find(&cs, "likes > ? AND subject like ?", 90, "新标题%").Error; err != nil {
log.Fatalln(err)
}
if err := DB.Where("likes > ? AND subject like ?", 90, "新标题%").Find(&cs).Error; err != nil {
log.Fatalln(err)
}
query := DB.Where("likes > ?", 90)
subject := "123"
if subject != "" {
query.Where("subject like ?", "新标题%")
}
query = DB.Where("likes > ?", 90)
subject = "新标题"
if subject != "" {
query.Or("subject like ?", subject+"%")
}
query = DB.Where("likes > ?", 90)
subject = "新标题"
if subject != "" {
query.Not("subject like ?", subject+"%")
query.Or(DB.Not("subject like ?", subject+"%"))
}
if err := query.Find(&cs).Error; err != nil {
log.Fatalln(err)
}
}
3.16 条件语法规则
func WhereType() {
var cs []Content
condA := DB.Where("subject < ?", 1).Or("subject > ?", 2)
condB := DB.Where("subject < ?", 3).Where(DB.Where("subject < ?", 4).Or("subject < ?", 5))
query := DB.Where(condA).Where(condB)
query = DB.Where(map[string]any{
"views": 100,
"id": []uint{1, 2, 3, 4, 5},
})
query = DB.Where(Content{
Subject: "GORM",
Vikes: 100,
})
if err := query.Find(&cs).Error; err != nil {
log.Fatalln(err)
}
}
func PlaceHolder() {
var cs []Content
query := DB.Where("likes = ? AND subject like ?", 100, "gorm%")
query = DB.Where("likes = @like AND subject like @subject",
sql.Named("subject", "gorm%"), sql.Named("like", 100))
query = DB.Where("likes = @like AND subject like @subject",
map[string]any{
"subject": "gorm%",
"like": 100,
})
if err := query.Find(&cs).Error; err != nil {
log.Fatalln(err)
}
}
3.17 字段排序和表达式排序
func OrderBy() {
var cs []Content
ids := []uint{2, 3, 1}
query := DB.Order("FIELD(id,2,3,1)")
query = DB.Clauses(clause.OrderBy{
Expression: clause.Expr{
SQL: "FIELD(id,?)",
Vars: []any{ids},
WithoutParentheses: true,
},
})
if err := query.Find(&cs, ids).Error; err != nil {
log.Fatalln(err)
}
for _, c := range cs {
fmt.Println(c.ID)
}
}
3.18 结果限定及分页
const (
DefaultPage = 1
DefaultPageSize = 12
)
type Pager struct {
Page, PageSize int
}
func Pagination(pager Pager) {
page := DefaultPage
if pager.Page != 0 {
page = pager.Page
}
pagesize := DefaultPageSize
if pager.PageSize != 0 {
pagesize = pager.PageSize
}
offset := pagesize * (page - 1)
var cs []Content
if err := DB.Offset(offset).Limit(pagesize).Find(&cs); err != nil {
log.Println(err)
}
for _, v := range cs {
fmt.Println(v.ID)
}
}
func Paginate(pager Pager) func(db *gorm.DB) *gorm.DB {
page := DefaultPage
if pager.Page != 0 {
page = pager.Page
}
pagesize := DefaultPageSize
if pager.PageSize != 0 {
pagesize = pager.PageSize
}
offset := pagesize * (page - 1)
return func(db *gorm.DB) *gorm.DB {
return db.Offset(offset).Limit(pagesize)
}
}
func PaginationScope(pager Pager) {
var cs []Content
if err := DB.Scopes(Paginate(pager)).Find(&cs).Error; err != nil {
log.Println(err)
}
for _, v := range cs {
fmt.Println(v.ID)
}
}
3.19 分组聚合过滤
func GroupHaving() {
DB.AutoMigrate(&Content{})
type Result struct {
AuthorID uint
TotalViews int
TotalLikes int
AvgViews float64
}
var re []Result
if err := DB.Model(&Content{}).
Select("author_id", "SUM(vikes) as total_views", "SUM(likes) as total_likes", "AVG(vikes) as avg_views").
Group("author_id").Having("total_views > ?", 99).
Find(&re).Error; err != nil {
log.Fatalln(err)
}
}
3.20 count合计
func Count(pager Pager) {
query := DB.Model(&Content{}).
Where("likes > ?", 99)
var count int64
if err := query.Count(&count).Error; err != nil {
log.Fatalln(err)
}
var cs []Content
if err := query.Scopes(Paginate(pager)).Find(&cs).Error; err != nil {
log.Println(err)
}
for _, v := range cs {
fmt.Println(v.ID)
}
}
3.21 迭代查询
func Iterator() {
rows, err := DB.Model(&Content{}).Rows()
if err != nil {
log.Fatalln(err)
}
defer func() {
_ = rows.Close()
}()
for rows.Next() {
var c Content
if err := DB.ScanRows(rows, &c); err != nil {
log.Fatalln(err)
}
fmt.Println(c.Subject)
}
}
3.22 锁子句
func Locking() {
var cs []Content
if err := DB.
Clauses(clause.Locking{Strength: "UPDATE"}).
Find(&cs).Error; err != nil {
log.Fatalln(err)
}
if err := DB.
Clauses(clause.Locking{Strength: "SHARE"}).
Find(&cs).Error; err != nil {
log.Fatalln(err)
}
}
3.23 子查询
func SubQuery() {
DB.AutoMigrate(&Author{}, &Content{})
whereSubQuery := DB.Model(&Author{}).Select("id").Where("status = ?", 0)
var cs []Content
if err := DB.Where("author_id IN (?)", whereSubQuery).Find(&cs).Error; err != nil {
log.Fatalln(err)
}
fromSubQuery := DB.Model(&Content{}).Select("subject", "likes").Where("publish_time IS NULL")
type Result struct {
Subject string
Likes int
}
var rs []Result
if err := DB.Table("(?) AS temp", fromSubQuery).
Where("likes > ?", 10).
Find(&rs).Error; err != nil {
log.Fatalln(err)
}
}
3.24 钩子方法 查询钩子
func (c *Content) AfterFind(db *gorm.DB) error {
if c.AuthorID == 0 {
c.AuthorID = 1
}
return nil
}
func FindHook() {
var c Content
if err := DB.First(&c, 13).Error; err != nil {
log.Fatalln(err)
}
fmt.Printf("%+v\n", c)
}
- AuthorID值赋为1
3.25 更新-主键条件更新及获取更新记录数
func UpdatePK() {
var c Content
if err := DB.Save(&c).Error; err != nil {
log.Fatalln(err)
}
fmt.Println("1:", c.ID)
if err := DB.Save(&c).Error; err != nil {
log.Fatalln(err)
}
fmt.Println("2:", c.ID)
}
func UpdateWhere() {
values := map[string]any{
"subject": "Where Update Row",
"likes": 10001,
}
result := DB.Model(&Content{}).
Omit("updated_at").
Where("likes > ?", 100).
Updates(values)
if result.Error != nil {
log.Fatalln(result.Error)
}
log.Println("updated rows num: ", result.RowsAffected)
}
func UpdateNOWhere() {
values := map[string]any{
"subject": "Where Update Row",
"likes": 101,
}
result := DB.Model(&Content{}).
Omit("updated_at").
Where("1").
Updates(values)
if result.Error != nil {
log.Fatalln(result.Error)
}
log.Println("updated rows num: ", result.RowsAffected)
}
3.26 更新-表达式值
func UpdateExpr() {
values := map[string]any{
"subject": "Where Update Row",
"likes": gorm.Expr("likes + ?", 10),
}
result := DB.Model(&Content{}).
Omit("updated_at").
Where("likes > ?", 100).
Updates(values)
if result.Error != nil {
log.Fatalln(result.Error)
}
log.Println("updated rows num: ", result.RowsAffected)
}
3.27 更新-Hook简单介绍
3.28 删除-基本主键条件删除操作
func DeleteWhere() {
result1 := DB.Delete(&Content{}, "likes < ?", 100)
if err := result1.Error; err != nil {
log.Fatalln(result1.Error)
}
result2 := DB.Where("likes < ?", 100).Delete(&Content{})
if err := result2.Error; err != nil {
log.Fatalln(err)
}
}
3.29 删除-软删除和永久删除
func FindDeleted() {
var c Content
DB.Delete(&c, 13)
if err := DB.Unscoped().First(&c, 13).Error; err != nil {
log.Fatalln(err)
}
fmt.Println("unscoped:", c)
}
func DeleteHard() {
var c Content
if err := DB.Unscoped().Delete(&c, 14).Error; err != nil {
log.Fatalln(err)
}
}
3.30 原生sql的执行和结果处理
func RawSelect() {
type Result struct {
ID uint
Subject string
Likes, Vikes int
}
var rs []Result
sql := "SELECT `id`,`subject`,`likes`,`vikes` FROM `msb_content` WHERE `likes` > ? ORDER BY `likes` DESC LIMIT ?"
if err := DB.Raw(sql, 99, 12).Scan(&rs).Error; err != nil {
log.Fatalln(err)
}
log.Println(rs)
}
func RawExec() {
sql := "UPDATE `msb_content` SET `subject` = CONCAT(`subject`,'-new postfix') WHERE `id` BETWEEN ? AND ?"
result := DB.Exec(sql, 20, 30)
if result.Error != nil {
log.Fatalln(result.Error)
}
log.Println(result.RowsAffected)
}
func RowAndRows() {
sql := "SELECT `id`,`subject`,`likes`,`vikes` FROM `msb_content` WHERE `likes` > ? ORDER BY `likes` DESC LIMIT ?"
rows, err := DB.Raw(sql, 99, 12).Rows()
if err != nil {
log.Fatalln(err)
}
for rows.Next() {
type Result struct {
ID uint
Subject string
Likes, Vikes int
}
var r Result
DB.ScanRows(rows, &r)
fmt.Println(r)
}
}
3.31 会话模式的基本使用
func SessionIssue() {
db := DB.Model(&Content{}).Where("vikes > ?", 100)
db.Where("likes > ?", 99)
var cs []Content
db.Find(&cs)
}
func SessionNew() {
db := DB.Model(&Content{}).Where("vikes > ?", 100).Session(&gorm.Session{})
var cs1 []Content
db.Where("likes > ?", 9).Find(&cs1)
var cs2 []Content
db.Where("likes > ?", 99).Find(&cs2)
}
3.32 会话模式的常用实操选项
func SessionOptions() {
db:=DB.Session(&gorm.Session{
SkipHooks:true,
})
db.Save(&Content{Subject: "no create hook"})
db := DB.Session(&gorm.Session{
DryRun: true,
})
stmt := db.Save(&Content{}).Statement
fmt.Println(stmt.SQL.String())
fmt.Println(stmt.Vars)
db := DB.Session(&gorm.Session{
PrepareStmt: true,
})
}
3.33 context上下文支持
func ContextTimeoutCancel() {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
defer cancel()
var cs []Content
if err := DB.WithContext(ctx).Limit(5).Find(&cs).Error; err != nil {
log.Fatalln(err)
}
fmt.Println(cs)
}