青训营笔记之GORM框架初体验 | 豆包MarsCode AI 刷题

49 阅读4分钟
Gorm框架

功能强大的ORM框架(Object Relationship Mapping),拥有很多开源扩展、应用广泛 (和数据库交互)

环境配置

数据库:利用docker desktop 拉取最新的mysql服务器到本地,并设置用户名和密码

## 拉取镜像文件
docker pull mysql:latest
## 运行容器,完成端口映射
docker run --name mysql-server -e MYSQL_ROOT_PASSWORD=rootpassword -p 3306:3306 -d mysql:latest
## 进入容器配置数据库
docker exec -it mysql-server mysql -uroot -prootpassword
## 创建数据库,并设置用户权限
CREATE DATABASE testdb;
CREATE USER 'newuser'@'%' IDENTIFIED BY 'newpassword';
GRANT ALL PRIVILEGES ON testdb.* TO 'newuser'@'%';
FLUSH PRIVILEGES;
EXIT;
## 验证主机能否连接到数据库(在docker desktop 对应mysql-server容器中的exec窗口下执行)
mysql -h 127.0.0.1 -P 3306 -uroot -prootpassword

go环境:下载安装go,确保 GOPATH 和 GOROOT 环境变量已正确设置
然后需要通过powershell/CMD 获取服务驱动,并初始化模块

go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

mkdir gorm-example
cd gorm-example
go mod init gorm-example
代码文件

--实现利用gorm增删改查

package main
import (
	"log"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)
// 定义 User 模型
type User struct {
	ID    uint   `gorm:"primaryKey;autoIncrement"`
	Name  string `gorm:"not null"`
	Email string `gorm:"unique"`
}
func main() {
	// 连接数据库
	dsn := "newuser:newpassword@tcp(localhost:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Fatalf("failed to connect database: %v", err)
	}
	// 自动迁移表结构
	db.AutoMigrate(&User{})
	// 清空表并重置主键
	db.Exec("TRUNCATE TABLE users")
	// 增加记录
	createUser(db, "hello", "world.com")
	// 查询记录
	getUserByID(db, 1)
	// 更新记录
	updateUser(db, 1, "not hello")
	// 查询记录
	getUserByID(db, 1)
	// 删除记录
	deleteUser(db, 1)
	// 查询记录
	getUserByID(db, 1)
}

// 增加记录
func createUser(db *gorm.DB, newName string, newEmail string) {
	user := User{Name: newName, Email: newEmail}
	result := db.Create(&user)
	if result.Error != nil {
		log.Fatalf("failed to create user: %v", result.Error)
	}
	log.Printf("User created with ID: %d", user.ID)
}

// 查询记录
func getUserByID(db *gorm.DB, id uint) {
	var user User
	result := db.First(&user, id)
	if result.Error != nil {
		log.Fatalf("failed to get user: %v", result.Error)
	}
	log.Printf("User found: %+v", user)
}

// 更新记录
func updateUser(db *gorm.DB, id uint, newName string) {
	var user User
	result := db.First(&user, id)
	if result.Error != nil {
		log.Fatalf("failed to get user: %v", result.Error)
	}

	user.Name = newName
	result = db.Save(&user)
	if result.Error != nil {
		log.Fatalf("failed to update user: %v", result.Error)
	}
	log.Printf("User updated: %+v", user)
}

// 删除记录
func deleteUser(db *gorm.DB, id uint) {
	var user User
	result := db.Delete(&user, id)
	if result.Error != nil {
		log.Fatalf("failed to delete user: %v", result.Error)
	}
	log.Printf("User deleted with ID: %d", id)
}
代码输出
go run main.go
PS E:\GoProject\gogogo\demoGorm> go run .\main.go
2024/11/28 10:14:48 User created with ID: 1
2024/11/28 10:14:48 User found: {ID:1 Name:hello Email:world.com}
2024/11/28 10:14:48 User updated: {ID:1 Name:not hello Email:world.com}
2024/11/28 10:14:48 User found: {ID:1 Name:not hello Email:world.com}
2024/11/28 10:14:48 User deleted with ID: 1

2024/11/28 10:14:48 E:/GoProject/gogogo/demoGorm/main.go:63 record not found
[2.173ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` LIMIT 1
2024/11/28 10:14:48 failed to get user: record not found
exit status 1

主要参考文档-GORM官方中文书册: gorm.io/zh_CN/docs/…

除去常见的增删改查任务,还可以使用常见的事务、hook等组件来提升操作的完整度

事务,为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除),而在GORM中也会出现事务的嵌套和手动事务来满足开发的需求,前者好处是可以回滚较大事务内执行的一部分操作,而后者则支持直接调用事务控制方法(commit、rollback),除此之外也提供如SavePoint、RollbackTo等等方法来保证事务回滚的高效

// 事务嵌套
db.Transaction(func(tx *gorm.DB) error {
  tx.Create(&user1)
  tx.Transaction(func(tx2 *gorm.DB) error {
    tx2.Create(&user2)
    return errors.New("rollback user2") // Rollback user2
  })
  return nil
})
// 手动控制事务
// 开始事务
tx := db.Begin()
// 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
tx.Create(...)
// ...
// 遇到错误时回滚事务
tx.Rollback()
// 否则,提交事务
tx.Commit()

hook,在创建、查询、更新、删除等操作之前、之后调用的函数,它会在创建、更新、查询、删除时自动被调用。如果任何回调返回错误,GORM 将停止后续的操作并回滚事务,默认形式func(*gorm.DB) error

// BeforeCreate 钩子,在创建对象之前执行
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
	log.Println("BeforeCreate hook called")
	return
}
// BeforeUpdate 钩子,在更新对象之前执行
func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {
	log.Println("BeforeUpdate hook called")
	return
}
// AfterCreate 钩子,在创建对象之后执行
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
	log.Println("AfterCreate hook called")
	return
}
// AfterUpdate 钩子,在更新对象之后执行
func (u *User) AfterUpdate(tx *gorm.DB) (err error) {
	log.Println("AfterUpdate hook called")
	return
}
// AfterDelete 钩子,在删除对象之后执行
func (u *User) AfterDelete(tx *gorm.DB) (err error) {
	log.Println("AfterDelete hook called")
	return
}
2024/11/28 14:36:20 BeforeCreate hook called
2024/11/28 14:36:20 AfterCreate hook called
2024/11/28 14:36:20 User created with ID: 1
2024/11/28 14:36:20 User found: {ID:1 Name:hello Email:world.com}
2024/11/28 14:36:20 BeforeUpdate hook called
2024/11/28 14:36:20 AfterUpdate hook called
2024/11/28 14:36:20 User updated: {ID:1 Name:not hello Email:world.com}
2024/11/28 14:36:20 User found: {ID:1 Name:not hello Email:world.com}
2024/11/28 14:36:20 AfterDelete hook called
2024/11/28 14:36:20 User deleted with ID: 1