这是我参与「第六届青训营 -后端场」笔记创作活动写下的第4篇笔记。
一、安装GORM库
首先,我们需要在Go项目中安装GORM库。可以使用以下命令进行安装:
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
/导入包之前否则显示标红/
二、连接数据库
在使用GORM之前,我们需要先连接到数据库。
以MySQL为例,连接数据库的步骤如下:
1、创建一个数据库:
- 设置用户名和密码以及连接名,后续会用
- 新建数据库
2、导入所需的包:
import (
"gorm.io/gorm"
"gorm.io/driver/mysql"
)
/在go语言中引入一个包,如果没有使用,需要添加下划线,否则会报错/
例如:
_"github.com/go-sql-driver-mysql"
"github.com/jinzhu/gorm"
_"gorm-1/testA"
添加下划线还有一个作用:可以初始化init()函数
在启动程序在main()之前会先被调用
3、创建数据库连接:
dsn := "username: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 {
// 处理连接错误
}
/其中,dsn是数据库连接字符串,username为用户名,password为用户密码,database_name为数据库名/
三、定义结构体模型
接下来,我们需要定义数据库表对应的模型结构体。例如,我们创建一个empolyee模型表示员工信息:
type employee struct {
Id int
Name string
Age int
}
四、创建表结构
在GORM中,可以使用AutoMigrate方法自动创建数据库表。在应用程序的入口处调用该方法即可:
db.AutoMigrate(&User{})
五、尝试运行
双击打开我们创建的数据库,会发现在"表"里已经出现了一个名为employees的表格
也可以创建单表,在26行后添加一句
sqlDB.SingularTable(true)
//开启单表属性
完整代码为:
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type employee struct {
Id int
Name string
Age int
}
func main() {
dsn := "root:123456@tcp(127.0.0.1:3306)/pract-list?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println("gorm.Open:", err)
return
}
sqlDB, err := db.DB()
if err != nil {
fmt.Println("db.DB:", err)
return
}
defer sqlDB.Close()
fmt.Println(db.AutoMigrate(new(employee)).Error)
}
六、gorm构建连接池
使用 GORM 构建连接池非常简单。GORM 库已经集成了连接池的功能,我们只需通过配置参数来设置连接池的大小和其他相关属性。
gorm构建连接池主要涉及三个步骤:
- 定义全局变量
var DB *gorm.DB
- 新建变量接收用gorm.Open方法构建连接池的句柄
- 修改属性
我们使用 db.DB() 获取 GORM 的底层 *sql.DB,然后可以调用其方法来设置连接池的大小和其他属性。
SetMaxOpenConns():设置最大打开连接数,即同时最大可以有多少个连接到数据库,默认为0(表示无限制)。
SetMaxIdleConns():设置最大空闲连接数,即连接池中最大可以空闲的连接数,默认为2。
SetConnMaxLifetime():设置连接的最大生命周期,即连接在连接池中的最长存活时间,默认为0(表示永久存活)。
// 设置连接池大小
sqlDB.SetMaxOpenConns(100) // 设置最大打开连接数
sqlDB.SetMaxIdleConns(10) // 设置最大空闲连接数
sqlDB.SetConnMaxLifetime(0) // 设置连接的最大生命周期
应该始终在使用完数据库连接后将其释放,所以最后我们使用 defer sqlDB.Close() 来确保连接在主函数结束时被关闭。
七、实现增删改查操作
1、创建记录(插入数据):
var emp employee
emp.Name = "小王"
emp.Age = 23
res:=db.Create(&emp)
fmt.Println(emp.Id)
fmt.Println(res.Error)
fmt.Println(res.RowsAffected)
声明一个名为emp的变量,并对Name和Age进行赋值。
2、更新数据
- 指定id更新字段
var emp employee
emp.Name = "阿红"
emp.Age = 24
emp.Id = 1
res :=db.Save(&emp)
- 条件更新
res :=db.Model(new(employee)).Where("name=?","阿红").Update("name","小二")
//这里是将name为”小红“的信息都修改为”小二“
- 多个字段更新
var emp employee
emp.Id = 2
res:=db.Model(&emp).Updates(map[string]interface{}{"name":"阿彬","age":18})
//这句可以实现修改多个数据
3、查询数据
获取第一条,按主键排序
db.First(&emp)
获取最后一条
db.Last(&emp)
如果需要查询多条记录,可以使用 Find 方法,以及将结果存储到 employees 切片中。
var emp []employee
db.Find(&emp)
使用 Select 方法可以指定要选择的字段
db.Select("name").First(&emp)
4、删除数据
主键删除
res := db.Delete(&emp)
八、结合gin封装增删查改
初始化引擎,以及路由注册初始化
r := gin.Default()
r.POST("/employees", createEmployee)
r.GET("/employees/:id", getEmployee)
r.PUT("/employees/:id", updateEmployee)
r.DELETE("/employees/:id", deleteEmployee)
1、增加操作:
- 在 Gin 中,创建一个路由处理函数,该函数接收客户端传递的数据,并将其绑定到结构体中。
- 使用
DB.Create(&emp)执行插入操作,并将插入的结果保存在result变量中。 - 检查
result.Error是否为空,如果非空,则表示插入出现错误,可以返回相应的错误响应给客户端。否则,返回成功的响应。
2、查询操作:
-
在 Gin 中,创建一个路由处理函数,该函数根据员工 ID 参数从 URL 中获取要查询的员工 ID。
-
使用
DB.First(&emp, id)执行查询操作,并将结果保存在result变量中。其中,&emp表示查询结果将保存到emp变量中,id是要查询的员工 ID。 -
检查
result.Error是否为空,如果非空,则表示查询出现错误,可以返回相应的错误响应给客户端。否则,返回查询到的员工信息作为成功响应。例如:
func getEmployee(c *gin.Context) { id := c.Param("id") var emp Employee if result := DB.First(&emp, id); result.Error != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Employee not found"}) return } c.JSON(http.StatusOK, gin.H{"data": emp}) }
3、更新操作:
- 在 Gin 中,创建一个路由处理函数,该函数根据员工 ID 参数从 URL 中获取要更新的员工 ID。
- 使用
DB.First(&emp, id)执行查询操作,以获取要更新的员工信息。 - 使用
c.ShouldBindJSON(&emp)将客户端传递的更新数据绑定到结构体中。 - 使用
DB.Save(&emp)执行更新操作,并将更新的结果保存在result变量中。 - 检查
result.Error是否为空,如果非空,则表示更新出现错误,可以返回相应的错误响应给客户端。否则,返回更新后的员工信息作为成功响应。
4、删除操作:
- 在 Gin 中,创建一个路由处理函数,该函数根据员工 ID 参数从 URL 中获取要删除的员工 ID。
- 使用
DB.First(&emp, id)执行查询操作,以获取要删除的员工信息。 - 使用
DB.Delete(&emp)执行删除操作,并将删除的结果保存在result变量中。 - 检查
result.Error是否为空,如果非空,则表示删除出现错误,可以返回相应的错误响应给客户端。否则,返回删除成功的消息作为成功响应。
func deleteEmployee(c *gin.Context) {
id := c.Param("id")
var emp Employee
if result := DB.First(&emp, id); result.Error != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Employee not found"})
return
}
if result := DB.Delete(&emp); result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("Employee %d deleted", emp.ID)})
}
参考资料: