使用gorm需要注意的点

1、慎用CreatedAt、UpdatedAt和DeletedAt字段

数据库设计字段时要避开这created_at、updated_at、deleted_at字段,因为被框架本身使用了,建议改为created_time、updated_time和deleted_time。

数据插入时,仅仅插入业务数据即可,created_at 和updated_at,deleted_at字段不用手动设置值,gorm会自动维护

2、查询时,如果没有查到记录也算一个err,需要在正常理解的err之前判断,类似如下的顺序:

复制代码
    err := db.Table(GroupChatTableName).Select("gc_status").Where(map[string]interface{}{
            "gc_id": gid,
        }).Find(&group).Error
    
    // 这个要在err前面,因为在gorm里找不到记录也算错误
    if db.RecordNotFound() {
        log.Errorf("query group chat not found")
        return 0, nil
    }
 
    if err != nil {
        log.Errorf("query group chat info by gid failed, err: %v", err)
        return 0, err
    }
复制代码

Find查询结果是列表,First查询的是单条数据。
当 First、Last、Take 方法找不到记录时,GORM 会返回 ErrRecordNotFound 错误【jinzhu版】

注意:io版本 的 Find 函数在进行查找时,如果查找结果为空,不会报record not found

3、在使用Raw自定义SQL查询时,使用Scan来接收数据,虽然Find也是可以接收的,但是Find主要还是用来带条件查询的,链接到Raw后面时条件是不起作用的,所以用Scan函数单纯的接收数据就行了。

4、更新单个字段用struct+update,更新多个字段用struct+updates(不更新零值),必须通过 map+ updates才能更新多个字段,且零值字段也会更新。

5、Save用于保存所有字段。提示: 相当于根据主键id,更新所有模型字段值。如果记录在数据库中已经存在,Save 方法就会更新该记录。如果不存在,则会插入一条新记录。默认会更新该对象的所有字段,即使没有赋值

db.First(&user)
user.Name = "jinzhu 2"
user.Age = 100
db.Save(&user)
// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;

6、进行数据库操作时,要考虑数据安全问题,注意对输入参数进行有效性验证,以避免SQL注入等安全问题出现。

7、当通过结构体进行查询时,GORM将会只通过非零值字段查询,这意味着如果你的字段值为0''false或者其他零值时,将不会被用于构建查询条件,例如:

db.Where(&User{Name: "jinzhu", Age: 0}).Find(&users)
//SELECT * FROM users WHERE name = "jinzhu";

若要在查询条件中包含零值,可以使用映射,该映射将包含所有键值作为查询条件,例如:

db.Where(map[string]interface{}{"Name": "jinzhu", "Age": 0}).Find(&users)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 0;

8、Count,该 model 能获取的记录总数。Count 必须是链式查询的最后一个操作 ,因为它会覆盖前面的 SELECT,但如果里面使用了 count 时不会覆盖。

9、默认是软删除,只会将DeletedAt 字段的值会被设置为当前时间。如果要永久删除,则使用Unscoped

// Unscoped 方法可以物理删除记录
db.Unscoped().Delete(&order)
//DELETE FROM orders WHERE id=10;

10、where的使用

jinzhu版在调用Where 时会创建一个副本,同一个 DB 在多行调用 Where 函数时内容不会叠加

io版同一个 DB 在多行调用 Where函数时内容会叠加

11、更新表达式,使用Expr函数

UPDATE foods SET stock = stock + 1 WHERE id = '2'

gorm提供了Expr函数用于设置表达式

db.Model(&food).Update("stock", gorm.Expr("stock + 1"))
//等价于: UPDATE `foods` SET `stock` = stock + 1  WHERE `foods`.`id` = '2'

12、日志大量出现 record not found

解决方式一:

db.Callback().Query().Before("gorm:query").Register("disable_raise_record_not_found", func(d *gorm.DB) {
  d.Statement.RaiseErrorOnNotFound = false
})

解决方式二:

复制代码
newLogger := logger.New(
  log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
  logger.Config{
    SlowThreshold:              time.Second,   // Slow SQL threshold
    LogLevel:                   logger.Silent, // Log level
    IgnoreRecordNotFoundError: true,           // Ignore ErrRecordNotFound error for logger
    ParameterizedQueries:      true,           // Don't include params in the SQL log
    Colorful:                  false,          // Disable color
  },
)

// Globally mode
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{
  Logger: newLogger,
})

// Continuous session mode
tx := db.Session(&Session{Logger: newLogger})
tx.First(&user)
tx.Model(&user).Update("Age", 18)
复制代码

总结:

  • 优点:提高开发效率
  • 缺点:使用反射牺牲性能,牺牲灵活性
posted @   李若盛开  阅读(771)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示