Gorm
先来聊聊所谓 ORM 到底是什么,其实 ORM 就是 Object-Relational Mapping 的缩写,它是一种编程技术,它将关系数据库中的数据映射到面向对象编程语言中的对象上。通俗点来说,就是用程序中的类和属性映射关系数据库中的表和字段,以此通过程序的逻辑代码对数据库进行操作。
而 Gorm 之于 Golang 就类似于 Hibernate或Mybatis 之于 Java 一样,这个比喻应该比较形象。也就是说,Gorm 并没有很好的抽象和封装化(毕竟对标的不是 Mybatis-Plus 等二次封装框架),而是直接将数据库操作的细节暴露给开发者,让开发者可以更加关注业务逻辑。
前置步骤
安装
go get gorm.io/gormgo get gorm.io/driver/mysql # 或者其他您使用的数据库驱动,例如 postgres、sqlite、sqlserver
连接数据库
package main
// 自动导入 gorm 包和对应数据库的驱动import ( "gorm.io/gorm" "gorm.io/driver/mysql")
func main() { // 此处 DataSourceName 中的具体连接数据,也可以通过环境变量、配置文件等方式获取 dsn := "user:password@tcp(127.0.0.1:3306)/database_name?charset=utf8mb4&parseTime=True&loc=Local" // 替换为您的数据库连接信息 db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect database") }
// 成功连接数据库后,db 变量就可以用来进行数据库操作了 println("Database connected successfully!")}
定义模型
所谓模型(Model)也就是数据库的表,逻辑代码的类。
type User struct { gorm.Model // 内嵌 gorm.Model,包含 ID、CreatedAt、UpdatedAt、DeletedAt 字段 Name string `gorm:"size:255"` // 字段名 Name,类型 string,gorm tag 定义字段长度 Email string `gorm:"unique"` // 字段名 Email,类型 string,gorm tag 定义唯一索引}
注意:gorm:"tag"
: GORM 可以这样来定义字段的数据库映射规则和约束,例如字段大小、唯一索引、是否可为空等等。这类似于 MyBatis-Plus 中的注解或 XML 配置
基本操作(CRUD)
创建表
db.AutoMigrate(&User{}) // 自动迁移 User 模型对应的表
增
// 1. 创建 User 实例user := User{Name: "Alice", Email: "alice@example.com"}// 2. 保存行记录到指定数据库result := db.Create(&user)
// 批量操作users := []*User{ {Name: "Jinzhu", Age: 18, Birthday: time.Now()}, {Name: "Jackson", Age: 19, Birthday: time.Now()},}result := db.CreateInBatches(users)
// 处理结果user.ID // 返回插入数据的主键result.Error // 返回 errorresult.RowsAffected // 返回插入记录的条数
查
First
:返回第一条匹配的记录,相当于ORDER BY id LIMIT 1
Take
:获取一条记录无指定排序顺序,相当于LIMIT 1
Last
:返回最后一条匹配的记录,相当于ORDER BY id DESC LIMIT 1
var u = new(User)db.First(u)
var uu Userdb.Find(&uu, "name = ?", "Alice")
var users1 []Userdb.Find(&users, "age <> ?", 18)
var users2 []Userdb.Find(&users, "name IN ?", []string{"Jinzhu", "Jackson"})
改
Select
:指定要更新的字段,在更新某条行记录时可指定只更新部分字段Omit
:忽略某些字段不更新
// 先查后更新// UPDATE `users` SET `age` = 20 WHERE `name` = 'Alice'var user Userdb.First(&user, "name = ?", "Alice")user.Age = 20db.Save(&user)
// 利用 save 保存的更新(若不存在则创建,若存在则更新)// UPDATE `users` SET `name` = 'jinzhu', `age` = 100 WHERE `id` = 1db.Save(&User{ID: 1, Name: "jinzhu", Age: 100})
// Model + Updates 是最推荐的方式var user Userdb.Find(&user, "name = ?", "Alice")db.Model(&user).Select("*").Updates(User{Age: 20, Name: "Jinzhu"})
删
db.Where("name = ?", "jinzhu").Delete(&email)db.Delete(&Email{}, "email LIKE ?", "%jinzhu%")
进阶操作
Builder
这个相当于 Mybatis-Plus 中的 Wrapper,可以用来构造复杂的查询条件。
// 原生 SQL 的执行var users []Userdb.Raw("UPDATE users SET name = ? WHERE age = ? RETURNING id, name", "jinzhu", 20).Scan(&users)
db.Exec("UPDATE users SET money = ? WHERE name = ?", gorm.Expr("money * ? + ?", 10000, 1), "jinzhu")
// 条件查询var users []User
db.Where("name LIKE ?", "%Ali%").Find(&users) // 模糊查询 Name 字段包含 "Ali" 的用户db.Where("name = ? AND email <> ?", "Alice", "alice@example.com").Find(&users) // 多条件查询
// Order 排序db.Order("name").Find(&users) // 按 Name 字段升序排序db.Order("name DESC").Find(&users) // 按 Name 字段降序排序
// Limit 和 Offset 分页db.Limit(10).Offset(20).Find(&users) // 分页查询,每页 10 条,从第 21 条开始
Joins
var users []Userdb.Joins("Orders").Where("orders.amount > ?", 100).Find(&users)
事务
// 嵌套事务(调用Transaction方法)err := db.Transaction(func(tx *gorm.DB) error { if err := tx.Create(&User{Name: "Alice"}).Error; err != nil { return err } if err := tx.Create(&User{Name: "Bob"}).Error; err != nil { return err } return nil})
if err != nil { // 事务回滚 fmt.Println("Transaction failed:", err)} else { // 事务提交 fmt.Println("Transaction success!")}
// 单独使用事务(调用Begin方法)tx := db.Begin()
// 事务内操作tx.Create(&User{Name: "Alice"})tx.Create(&User{Name: "Bob"})
// 事务提交tx.Commit()// 事务回滚tx.Rollback()