一、Go 语言与 ORM 简介
Go 是一种开源的编程语言,它具有高效、简洁、并发性能强等特点,在后端开发、云计算、分布式系统等领域得到广泛应用。
对象关系映射(Object Relational Mapping,简称 ORM)是一种编程技术,它允许开发者使用面向对象的编程语言来操作关系型数据库,而无需编写大量的原生 SQL 语句。通过 ORM,开发者可以将数据库表映射为编程语言中的对象,对对象的操作会自动转换为对数据库的操作,大大提高了开发效率和代码的可维护性。
二、Go 的 ORM 库概述
Go 语言中有多个 ORM 库可供选择,常见的有以下几个:
-
GORM:功能强大且灵活,支持多种数据库,如 MySQL、PostgreSQL、SQLite 等,具有丰富的功能,如关联查询、事务处理、钩子函数等,是目前使用较为广泛的 Go ORM 库。
-
Xorm:简单易用,对数据库的操作提供了简洁的 API,也支持多种数据库,在一些项目中也有应用。
-
Bee ORM:以简单快速著称,能够快速进行数据库开发,但功能相对 GORM 可能稍显逊色。
GORM 功能强大、活跃的社区支持,用的多。
三、使用 GORM 连接 MySQL
以下是使用 GORM 连接 MySQL 数据库的基本步骤:
首先,安装 Go 环境和 MySQL 数据库。go安装gorm框架和驱动
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
然后使用以下代码进行连接:
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
// 定义数据库连接字符串,格式为:用户名:密码@(主机地址:端口号)/数据库名?参数
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
// 使用 GORM 的 MySQL 驱动打开数据库连接
db, err := gorm.Open(mysql.Open(dsn), ```
&gorm.Config{
NamingStrategy: schema.NamingStrategy{
TablePrefix: "", // 表前缀
SingularTable: true, // 禁用表名复数
}})
if err!= nil {
panic(err)
}
// 这里可以进行后续的数据库操作
}
dsn 包含了连接 MySQL 所需的信息,如用户名、密码、主机地址、端口号、数据库名以及一些字符集和时间解析的参数。gorm.Open 函数使用 mysql.Open 方法传入连接字符串来建立与 MySQL 数据库的连接,并返回一个 gorm.DB 类型的数据库对象,通过该对象可以进行各种数据库操作。
四、GORM 的增删改查操作
(一)定义数据模型
在进行增删改查操作之前,需要先定义与数据库表对应的结构体模型。
type User struct {
ID uint `gorm:"primaryKey"`
Name string
Age int
}
// TableName 指定表名
func (Stu) TableName() string { return "student" }
也可以通过连接配置指定表名
(二)创建记录(插入操作)
使用 Create 方法向数据库中插入一条记录:
func main() {
// 创建一个 User 实例
user := User{Name: "fes", Age: 18}
// 将 user 插入到数据库中
result := db.Create(&user)
if result.Error!= nil {
panic(result.Error)
}
// 插入成功后,user 的 ID 会被自动赋值
fmt.Println(user.ID)
}
(三)查询记录
- 查询单个记录:可以使用
First或Take方法查询单个记录。例如,根据ID查询用户:
var user User
// 根据主键查询
db.First(&user, 1)
// 或者使用 Take 方法
// db.Take(&user, 1)
if user.ID == 0 {
fmt.Println("未找到记录")
} else {
fmt.Printf("用户姓名:%s,年龄:%d\n", user.Name, user.Age)
}
2. 查询多条记录:使用 Find 方法查询多条记录。例如,查询所有用户:
var users []User
db.Find(&users)
for _, u := range users {
fmt.Printf("用户姓名:%s,年龄:%d\n", u.Name, u.Age)
}
(四)更新记录
使用 Save 或 Updates 方法更新记录。例如,更新用户的年龄:
var user User
db.First(&user, 1)
user.Age = 30
// 使用 Save 方法更新
db.Save(&user)
// 或者使用 Updates 方法,指定要更新的字段
// db.Model(&user).Updates(User{Age: 30})
(五)删除记录
使用 Delete 方法删除记录。例如,删除指定 ID 的用户:
复制
db.Delete(&User{}, 1)
五、GORM 工程化
在实际工程中,首先要规划好项目的目录结构。通常会有一个models目录用于存放数据库模型结构体,一个database目录用于存放数据库连接相关的代码
package database
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB *gorm.DB
func Connect() {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
var err error
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err!= nil {
panic(err)
}
}
package models
import "gorm.io/gorm"
type User struct {
ID uint `gorm:"primaryKey"`
Name string
Age int
// 可以添加更多字段和标签,如创建时间、更新时间等
CreatedAt time.Time
UpdatedAt time.Time
}
业务逻辑处理阶段
- **创建操作**:
func GetUserByID(c *gin.Context) {
id := c.Param("id")
var user models.User
result := database.DB.First(&user, id)
if result.Error!= nil {
c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
return
}
c.JSON(http.StatusOK, user)
}
-
更新操作:
- 假设要更新用户的年龄,函数可以这样编写:
func UpdateUserAge(c *gin.Context) {
id := c.Param("id")
var user models.User
result := database.DB.First(&user, id)
if result.Error!= nil {
c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
return
}
var updateData struct {
Age int
}
if err := c.BindJSON(&updateData); err!= nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user.Age = updateData.Age
result = database.DB.Save(&user)
if result.Error!= nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error})
return
}
c.JSON(http.StatusOK, user)
}
-
删除操作:
- 要删除用户的函数如下:
func DeleteUser(c *gin.Context) {
id := c.Param("id")
result := database.DB.Delete(&models.User{}, id)
if result.Error!= nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error})
return
}
c.JSON(http.StatusOK, gin.H{"message": "用户删除成功"})
}
然后在main.go中启动 HTTP 服务器:
package main
import (
"myproject/database"
"myproject/routers"
"log"
"net/http"
)
func main() {
database.Connect()
router := routers.SetupRoutes()
log.Fatal(http.ListenAndServe(":8080", router))
}
六、GORM 的连接池池化功能
GORM 使用 database/sql 标准库的连接池功能。在 gorm.io/driver/mysql 包内部,当创建数据库连接时,会基于 database/sql 的连接池机制进行连接的管理。
database/sql 的连接池默认会维护一定数量的空闲连接,当有数据库操作请求时,如果有空闲连接则直接使用,否则会创建新的连接,直到达到最大连接数限制。连接在使用完成后会被放回连接池,供后续请求复用。
可以通过 database/sql 提供的一些函数和参数来配置连接池的行为,例如设置最大空闲连接数、最大连接数、连接的生命周期等。在 GORM 通过 gorm.Config 结构体中的一些配置项来间接影响连接池的设置,例如设置连接的最大空闲时间等。
七、GORM 与 SpringBoot 的 mybatis等ORM 区别
感觉是mybatis的灵活性更好,能编写比较灵活的SQL语句;GORM需要SQL语句拼接