GORM 连接数据库及CRUD | 青训营

153 阅读4分钟

GORM 是一个 Go 语言 ORM 库,它的目标是将数据库访问映射到 Go 语言中,构建一个友好的数据库访问层,对开发者隐藏底层的实现细节。本文主要记录了 GORM 连接MySQL数据库及CRUD的过程。

1. 依赖

使用 GORM 需要安装gorm.io/gorm和相应的数据库驱动,这里使用 MySQL,所以还需要安装gorm.io/driver/mysql

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

2. 连接数据库

var db *gorm.DB

func InitDB() error {
	dsn := "go-gorm-db:123456#QWErty@tcp(localhost:3306)/go-gorm-db?charset=utf8mb4&parseTime=True&loc=Local"
	var err error
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		return err
	}
	return nil
}

预先创建一个名为go-gorm-db的数据库,然后创建专门用于连接数据库的用户go-gorm-db,并授予该用户对go-gorm-db数据库的合适权限,包括SELECTINSERTUPDATEDELETE等。

程序开始时,调用InitDB()函数连接数据库,dsn是数据库连接字符串,其中包含了连接数据库的用户名、密码、地址、端口、数据库名等信息。

这样,就可以以go-gorm-db的用户身份连接到go-gorm-db数据库了。后续的CRUD操作都在db对象上进行。

3. 创建模型

使用 GORM 需要定义模型。模型是一个结构体,结构体的字段对应数据库表中的列。GORM 使用这个模型来处理数据库表中的数据。

type User struct {
	ID       uint   `json:"id" gorm:"primary_key"`
	Username string `json:"username"`
	Password string `json:"password"`
	Email    string `json:"email"`
	Phone    string `json:"phone"`
	Age      uint   `json:"age"`
}

func (u *User) TableName() string {
	return "user"
}

模型的定义中,使用标签gorm:"primary_key"标记了主键,使用标签json:"xxx"标记了字段在序列化时的名称。

TableName()方法返回模型对应的数据库表名,这里是user,如果没有定义该方法,GORM 会默认使用模型的结构体名称的复数形式作为表名。

4. 增删改查

这里使用gin框架创建一个简单的HTTP服务,对于每个增删改查操作,都定义一个相应的接口。

r := gin.Default()
// ...
r.Run(":8080")

4.1 Create

func (u *User) CreateUser(user User) error {
	return db.Create(&user).Error
}

db.Create()方法用于创建一条记录,参数是一个指向模型的指针或模型的切片。这里使用&user传入指针。

接口: PUT /users

r.PUT("/users", func(c *gin.Context) {
	var user controllers.User
	if err := c.BindJSON(&user); err != nil {
		// ...
	}
	if err := userHandler.CreateUser(user); err != nil {
		// ...
	}
	c.JSON(200, gin.H{
		"message": "success",
	})
})

4.2 Read

func (u *User) GetUserByID(id uint) (User, error) {
	var user User
	err := db.Where("id = ?", id).Find(&user).Error
	return user, err
}

db.Where()方法用于指定查询条件,db.Find()方法用于查询记录。这里使用&user传入指针。

查询条件可以是query字符串,也可以是结构体。使用结构体时,GORM只会将结构体中的非零值字段作为查询条件。

接口: GET /users/:id

r.GET("/users/:id", func(c *gin.Context) {
	id := c.Param("id")
	uid, err := strconv.Atoi(id)
	if err != nil {
		// ...
	}
	user, err := userHandler.GetUserByID(uint(uid))
	if err != nil {
		// ...
	}
	c.JSON(200, gin.H{
		"data":    user,
		"message": "success",
	})
})

4.3 Update

func (u *User) UpdateUser(id uint, user User) error {
	user.ID = 0
	return db.Model(&User{
		ID: id,
	}).Updates(user).Error
}

db.Model()方法用于指定模型,db.Updates()方法用于更新记录。这里使用&User{ID: id}传入指针。

接口: POST /users/:id

r.POST("/users/:id", func(c *gin.Context) {
	id := c.Param("id")
	uid, err := strconv.Atoi(id)
	if err != nil {
		// ...
	}
	var user controllers.User
	if err := c.BindJSON(&user); err != nil {
		// ...
	}
	if err := userHandler.UpdateUser(uint(uid), user); err != nil {
		// ...
	}
	c.JSON(200, gin.H{
		"data":    user,
		"message": "success",
	})
})

4.4 Delete

func (u *User) DeleteUser(id uint) error {
	return db.Delete(&User{}, id).Error
}

db.Delete()方法用于删除记录。这里指定删除&User{},并传入主键id

如果模型中有DeletedAt字段,那么删除记录时,GORM会将该字段的值设置为当前时间,而不是真正地从数据库中删除记录,实现软删除。

接口: DELETE /users/:id

r.DELETE("/users/:id", func(c *gin.Context) {
	id := c.Param("id")
	uid, err := strconv.Atoi(id)
	if err != nil {
		// ...
	}
	if err := userHandler.DeleteUser(uint(uid)); err != nil {
		// ...
	}
	c.JSON(200, gin.H{
		"message": "success",
	})
})

5. 总结与思考

后端的开发离不开增删改查这几个操作,无非是简单的CRUD和复杂的CRUD,GORM可以帮助我们完成这些操作,提高开发效率。

GORM 的使用较为简单,只需要定义模型,然后在模型上调用db.Create()db.Find()db.Updates()db.Delete()等方法即可实现增删改查。

GORM 还提供了更多的功能,比如事务、连接池、钩子、预加载、分页、软删除等,可以根据实际需要进行使用。