编程笔记

lifelong learning & practice makes perfect

using gorm

CURD

Create

json自定义字段使用

  1. 如下为system使用自定义字段

    1
    2
    3
    type System struct{
    Version string
    }
  2. 为自定义类型实现接口Value/Scan

    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
    func (s System)Value()(driver.Value, error) {
    bytes, err := json.Marshal(s)
    return string(bytes), err
    }

    func (s *System) Scan(value interface{}) error {
    var bytes []byte
    switch v := value.(type) {
    case []byte:
    bytes = v
    case string:
    bytes = []byte(v)
    default:
    return fmt.Errorf("解析失败,原始数据:%v", value)
    }

    result := System{}
    if len(bytes) <= 0 {
    *s = result
    return nil
    }
    err := json.Unmarshal(bytes, &result)
    *s = result
    return err
    }
  3. json查询,例如这里要查询version=1.0的System

    1
    2
    select * from table_t
    where system->'$.version' = "1.0"

Update

Retrieve

预加载,preload

外键tag

预加载依赖在领域层结构体变量的gorm tag,需要在结构体上变量上增加外键tag,tag有多种写法,根
领域对象间的不同关系如:belongs to/has one/has many等有不同写法.

  1. belongs to 参考: https://gorm.io/zh_CN/docs/belongs_to.html
  2. has one
  3. has many
  4. many to many
    在项目ForeignKey,References这两个标签最常用,主要用于Preload相关数据
自定义预加载,可在预加载时添加条件实现排序等功能
  1. 排序

    1
    2
    3
    4
    5
    6
    7
    // 文档:https://gorm.io/zh_CN/docs/preload.html
    //您可以通过 func(db *gorm.DB) *gorm.DB 实现自定义预加载 SQL,例如:

    db.Preload("Users", func(db *gorm.DB) *gorm.DB {
    return db.Order("user.age DESC")
    }).Find(&users)
    // SELECT * FROM user WHERE id IN (1,2,3,4) order by user.age DESC;

2.

order by

  1. 常用
    指定从数据库检索记录时的排序方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    db.Order("age desc, name").Find(&users)
    // SELECT * FROM users ORDER BY age desc, name;

    // 多个 order
    db.Order("age desc").Order("name").Find(&users)
    // SELECT * FROM users ORDER BY age desc, name;

    db.Clauses(clause.OrderBy{
    Expression: clause.Expr{SQL: "FIELD(id,?)", Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true},
    }).Find(&User{})
    // SELECT * FROM users ORDER BY FIELD(id,1,2,3)
  2. order by field 自定义排序
    使用上面的写法通过自定义字段排序时注意,WithoutParentheses为true,为false是构建的sql为order by field(column,(“f1,f2,f3,…”)),会报错

  3. 组合排序

    1
    2
    3
    select id,status,create_time
    FROM `order`
    ORDER BY FIELD(status,'s3','s2','s1')desc,create_time desc

    如上的sql使用gorm框架可以这么写:

    1
    2
    3
    4
    5
    6
    7
    8
    res:=[]*Order{}
    db.Clauses(clause.OrderBy{
    Expression: clause.Expr{
    SQL: "FIELD(status,?) DESC,create_time DESC",
    Vars: []interface{}{
    []string{"s3","s2","s1"},
    },
    WithoutParentheses: true}}).Find(&res)

    不能使用链式调用(gorm v2版本,版本号:gorm.io/gorm v1.20.11),如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    db.Clauses(clause.OrderBy{
    Expression: clause.Expr{
    SQL: "FIELD(status,?) DESC",
    Vars: []interface{}{
    []string{"s3","s2","s1"},
    },
    WithoutParentheses: true}}).
    Order("create_time DESC").
    Find(&res)
  4. 参考文档

索引

  1. 强制索引

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import "gorm.io/hints"

    db.Clauses(hints.UseIndex("idx_user_name")).Find(&User{})
    // SELECT * FROM `users` USE INDEX (`idx_user_name`)

    db.Clauses(hints.ForceIndex("idx_user_name", "idx_user_id").ForJoin ()).Find(&User{})
    // SELECT * FROM `users` FORCE INDEX FOR JOIN (`idx_user_name`, `idx_user_id`)"

    db.Clauses(
    hints.ForceIndex("idx_user_name", "idx_user_id").ForOrderBy(),
    hints.IgnoreIndex("idx_user_name").ForGroupBy(),
    ).Find(&User{})

    Index 用于提高数据检索和 SQL 查询性能。 Index Hints 向优化器提供了在查询处理过程中如何选择索引的信息。与 optimizer 相比,它可以更灵活地选择更有效的执行计划

    • 加了join
    1
    2
    3
    4
    db.Table("`order` FORCE INDEX (order_create_time_d977ab1e,idx_demand_number,   idx_stocked_number,idx_di)").
    //Clauses(hints.CommentBefore("from", "FORCE INDEX (order_create_time_d977ab1e, idx_demand_number,idx_stocked_number,idx_di)")).
    // 这样写,生成的sql语句有问题,force index位置在where条件中间
    Joins("left join servicelist on order.service_list_id=servicelist.id").Find(& orders)

Delete

Config

ConnPool

  1. gorm 连接池配置通过sql.DB实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    gormDB,err:=gorm.Open(...)
    db,err:=gormDB.DB()
    if err!=nil{
    return
    }
    db.SetConnMaxLifetime() //连接最长复用时间
    db.SetConnMaxIdleTime() //maximum amount of time a connection may be idle,最长空闲时间
    db.SetMaxIdleConns() // 最长空闲时间 maximum number of connections in the idle connection pool
    db.SetMaxOpenConns() // 最大连接数 maximum number of open connections to the database

欢迎关注我的其它发布渠道