GORM 介绍和简单使用
GORM
Gorm: 一个迭代超过十年的,快速的,对开发者友好的, 由 Golang 开发的 ORM 框架
Gorm 的基本使用
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// Declaring Models
type Product struct {
Code string
Price uint
}
func (p Product) TableName() string {
return "Product"
}
func main() {
db, err := gorm.Open(mysql.Open(
"user:pass@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// Create
db.Create(&Product{Code: "D42", Price: 332})
// Read
var product Product
db.First(&product, 1) // find product with integer primary key
db.First(&product, "code = ?", "D42") // find product with code D42
// Update - update product's price to 200
db.Model(&product).Update("Price", 200)
// Update - update multiple fields
db.Model(&product).Updates(Product{Price: 200, Code: "F42"}) // non-zero fields
db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})
// Delete - delete product
db.Delete(&product, 1)
}
GORM 支持的数据库
1. MySQL
2. SQLServer
3. PostgreSQL
4. SQLite
连接数据库的方法
import (
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
dsn := "user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
在 MySQL 中为保证 time.Time 正确性, 在 DSN 中我们还需要添加 parseTime 参数,为了更好支持 UTF8 我们需要添加 charset=utf8mb4
可以看出GORM是通过驱动进行数据库的连接,需要其它数据库是更换驱动即可(当然可能还有存在一些数据处理的细微差别需要进行修改
GORM 创建数据
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
result := db.Create(&user) // pass pointer of data to Create
user.ID // returns inserted data's primary key
result.Error // returns error
result.RowsAffected // returns inserted records count
我们可以通过 clause.OnConflict 处理数据的冲突,我们还可以设置 filed 的默认值
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
db.Clauses(clause.OnConfilict{DoNothing:true}).Create(&user)
// set Default values
type User struct {
ID int64
Name string `gorm:"default:galeone"`
Age int64 `gorm:"default:18"`
uuid.UUID UUID `gorm:"type:uuid;default:gen_random_uuid()"` // db func
}
GORM 查询数据
GORM 查询提供的方法
- First: 查询第一条记录
- Take
- Last: 查询最后一条记录
// Get the first record ordered by primary key
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;
// Get one record, no specified order
db.Take(&user)
// SELECT * FROM users LIMIT 1;
// Get last record, order by primary key desc
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;
result := db.First(&user)
result.RowsAffected // returns found records count
result.Error // returns error
// check error ErrRecordNotFound
errors.Is(result.Error, gorm.ErrRecordNotFound)
查询时默认会附加上 LIMIT 1,记录不存在时返回 ErrRecordNotFound,但是只有查询单条记录才会返回, first/last 通过主键进行查询,查询的struct 或者 model value ,不存在则采用第一个 field
GORM 更新数据
// struct update
// Update with conditions 单笔数据更新
db.Model(&User{}).Where("active = ?", true).Update("name", "hello")
// Update attributes with `struct`, will only update non-zero fields 多笔数据更新
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// Select with Map
// User's ID is `111`:
// 通过 map or select
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
struct update 只会 update 非零值, 要更新零值需要通过 map 或者 select
GORM 删除数据
数据的删除一般有两种方式,一种是物理的删除,直接从磁盘上删除,一种时软删除,就是对某些 field 进行标记,在查询忽略已标记特定 field的记录
type User struct {
ID int
Deleted gorm.DeletedAt
Name string
}
// Email's ID is `10`
db.Delete(&email)
// DELETE from emails where id = 10;
// Delete with additional conditions
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";
// query soft deleted record
db.Unscoped().Where("age = 20").Find(&users)
// SELECT * FROM users WHERE age = 20;
// 物理删除 软删除的数据
db.Unscoped().Delete(&order)
// DELETE FROM orders WHERE id=10;
如果 struct 或者 model 存在 gorm.DeletedAt field 删除则是采用软删除,我们需要软删除的数据我们可以 call Unscoped(),
GORM 事务
GORM 提供联Begin commit rollback 用于事务
操作的基本流程
// begin a transaction
tx := db.Begin()
// do some database operations in the transaction (use 'tx' from this point, not 'db')
tx.Create(...)
// ...
// rollback the transaction in case of error
tx.Rollback()
// Or commit the transaction
tx.Commit()
for exampl
func CreateAnimals(db *gorm.DB) error {
// Note the use of tx as the database handle once you are within a transaction
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if err := tx.Error; err != nil {
return err
}
if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
tx.Rollback()
return err
}
return tx.Commit().Error
}
在开发中我们难免会遇到忘记对事务进行提交所以我们就可以通过 GORM 提供的 transaction 对操作进行包裹
db.Transaction(func(tx *gorm.DB) error {
// do some database operations in the transaction (use 'tx' from this point, not 'db')
if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
// return any error will rollback
return err
}
if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
return err
}
// return nil will commit the whole transaction
return nil
})
Note: 我们可以通过设置 SkipDefaultTransaction filed 选择是否使用事务
Reference
- GORM Doc
- 字节跳动青训营