Golang学习&DATABASE/SQL与GORM设计与实践 | 青训营笔记04

DATABASE/SQL与GORM 设计与实践

1.理解 database/sql

  • 连接数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import (
"database/sql"
"time"

_ "github.com/go-sql-driver/mysql"
)

// ...

db, err := sql.Open("mysql", "user:password@/dbname")
if err != nil {
panic(err)
}
// See "Important settings" section.
db.SetConnMaxLifetime(time.Minute * 3)
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(10)
  • DB连接的几种类型
    • 直接连接/Conn
    • 预编译/Stmt
    • 事务/TX
  • 处理返回数据的几种方式
    • Exec/ ExecContext -> Result
    • Query / QueryContext -> Rows (Columns)
    • QueryRow / QueryRowContext -> Row (Rows简化)

2.GORM基础使用

GORM:设计简洁、功能强大、自由扩展的全功能ORM (对象关系映射)

  • 设计原则:API精简、测试优先、最小惊讶、灵活扩展、无依赖 可信赖

  • 功能完善:

    • 关联:一对一、一对多、单表自关联、多态;Preload、Joins 预加载、级联删除;关联模式;自定义关联表
    • 事务:事务代码块、嵌套事务、Save Point
    • 多数据库、读写分离、命名参数、Map、子查询、分组条件、代码共享、SQL表达式(查询、创建、更新)、自动选字段、查询优化器
    • 字段权限、软删除、批量数据处理、Propared Stmt、自定义类型、命名策略、虚拟字段、自动track 时间、SQLBuilder、Logger
    • 代码生成、复合主键、Constraint、Prometheus、Auto Migration、真·跨数据库兼容
    • 多模式灵活自由扩展
    • Dovelopor Friondly

    - 简单创建连接

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import (
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
    )

    func main() {
    // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
    dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    }

    - 高级配置

    1
    2
    3
    4
    5
    6
    7
    8
    db, err := gorm.Open(mysql.New(mysql.Config{
    DSN: "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // DSN data source name
    DefaultStringSize: 256, // string 类型字段的默认长度
    DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
    DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
    DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
    SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
    }), &gorm.Config{})

    - CRUD

- 模型定义

1
2
3
4
5
6
7
8
9
10
11
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}

- 约定大于配置

  • GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间。

  • 遵循 GORM 已有的约定,可以减少您的配置和代码量。如果约定不符合您的需求,GORM 允许您自定义配置它们。

使用 ID 作为主键

默认情况下,GORM 会使用 ID 作为表的主键。

1
2
3
4
type User struct {
ID string // 默认情况下,名为 `ID` 的字段会作为表的主键
Name string
}

你可以通过标签 primaryKey 将其它字段设为主键

1
2
3
4
5
6
7
// 将 `UUID` 设为主键
type Animal struct {
ID int64
UUID string `gorm:"primaryKey"`
Name string
Age int64
}

复数表名

GORM 使用结构体名的 蛇形命名 作为表名。对于结构体 User,根据约定,其表名为 users

TableName

您可以实现 Tabler 接口来更改默认表名,例如:

1
2
3
4
5
6
7
8
type Tabler interface {
TableName() string
}

// TableName 会将 User 的表名重写为 `profiles`
func (User) TableName() string {
return "profiles"
}

简单总结:

  • GORM是一种对象关系映射ORM框架,数据表对应结构体,数据行对应结构体实例,数据库字段对应结构体字段。

  • 在gorm中,表名默认就是结构体名称的复数,也可以通过方法或者db.Table(“表名”)自定义表名;

  • 列名由两个单词组成,在数据库中默认转小写后用下划线链接;

  • 如果结构体有ID字段则默认ID字段为主键。

  • 另外,GORM内置了一个gorm.Model结构体。gorm.Model是一个包含了ID, CreatedAt, UpdatedAt, DeletedAt四个字段的Golang结构体,可以将其嵌入到自己的结构体中。(如果模型内置了gorm.model有DeletedAt字段,则调用Delete删除该记录时,将会设置DeletedAt字段为当前时间,而不是直接将记录从数据库中删除,即软删除)

  • gorm中支持的结构体tag:

1
2
3
4
5
6
7
Type    指定列数据类型
Size 指定列大小, 默认值255
PRIMARY_KEY 将列指定为主键
UNIQUE 将列指定为唯一
NOT NULL 将列指定为非 NULL
Column 指定列名
default 设置默认值
例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
查询

db.Select("name, age").Order("age desc").Limit(3).Find(&user, "name = ?", "jinzhu")
db.Select("name, age").Order("age desc").Limit(3).Where("name = ?","jinzhu").Find(&users)
修改
// 根据给定的条件更新单个属性
db.Model(&user).Where("active = ?", true).Update("name", "hello")
// 使用 map 更新多个属性,只会更新其中有变化的属性
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// 使用 struct 更新多个属性,只会更新其中有变化且为非零值的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18})

如果你想更新或忽略某些字段,你可以使用 Select,Omit

删除
db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
db.Delete(Email{}, "email LIKE ?", "%jinzhu%")
  • 在 GORM 中使用多个立即执行方法时,后一个立即执行方法会复用前一个立即执行方法的条件 (不包括内联条件,find中写的条件) 。立即执行方法是指那些会立即生成SQL语句并发送到数据库的方法,一般是CRUD方法,如:Create, First, Find, Take, Save, UpdateXXX, Delete, Scan, Row, Rows…

  • db.debug 可以返回查询的sql语句。


Golang学习&DATABASE/SQL与GORM设计与实践 | 青训营笔记04
https://zty-f.github.io/2022/05/18/Golang学习-DATABASE-SQL与GORM设计与实践-|-青训营笔记04/
作者
ZTY
发布于
2022年5月18日
更新于
2025年1月2日
许可协议