Gorm 是一个流行的 Go 语言的 ORM(对象关系映射)库,用于在 Go 语言中进行数据库操作。它提供了简洁的 API 和强大的功能,帮助开发者简化数据库的操作和管理。Gorm 支持多种关系型数据库,包括 MySQL、PostgreSQL、SQLite 和 SQL Server 等。它提供了一种面向对象的方式来处理数据库,将数据库表映射为 Go 结构体,并提供了丰富的方法来执行增删改查等操作。
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
CREATE DATABASE IF NOT EXISTS database_name
`注意: 可以在 navicat 上直接新建查询创建。
gorm.Open
的函数签名如下:
func Open(dialect string, args ...interface{}) (*gorm.DB, error)
参数说明:
dialect
是数据库的方言,表示要连接的数据库类型,如 “mysql”、“postgres”、“sqlite3” 等。args
是连接数据库时的参数,如连接字符串等,具体根据不同的数据库类型和驱动而有所不同。在调用 gorm.Open
时,你需要传入合适的数据库方言和连接参数,以便与目标数据库建立连接。根据不同的数据库类型和驱动,连接参数的格式会有所不同。
以下是一个示例,展示如何使用 gorm.Open
建立与 MySQL 数据库的连接:
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
dsn := "root:123456@tcp(127.0.0.1:3306)/database_name?charset=utf8mb4&parseTime=True&loc=Local"
// 建立与数据库的连接
_, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
fmt.Println("connection succeeded")
}
在上述示例中,我们使用 “mysql” 方言和连接字符串来连接 MySQL 数据库。连接字符串的格式根据不同的数据库和驱动而有所不同,你需要替换示例中的 username
、password
和 database_name
为你实际的数据库连接信息。
请注意,在使用 Gorm 进行数据库操作之前,你需要确保成功建立与数据库的连接,以便后续的增删改查操作能够顺利进行。
// User gorm.Model 定义
type User struct {
ID uint `gorm:"primary_key"`
Name string `gorm:"size:255"`
Age int
}
Gorm有内置的日志记录器支持,默认情况下,它会打印发生的错误
// 启用Logger,显示详细日志
db.LogMode(true)
// 禁用日志记录器,不显示任何日志
db.LogMode(false)
// 调试单个操作,显示此操作的详细日志
db.Debug().Where("name = ?", "jinzhu").First(&User{})
// 自动迁移数据库表结构
err := db.AutoMigrate(&User{})
if err != nil {
log.Fatal(err)
}
插入数据:使用 Gorm,你可以使用 Create
函数创建新的记录。例如:
// CreateUser 创建用户
func CreateUser(db *gorm.DB, name string, age int) error {
user := User{
Name: name,
Age: age,
}
return db.Create(&user).Error
}
查询单个数据:使用 Gorm,你可以使用 Find
函数查询记录。例如:
// GetUserByID 通过id查找用户
func GetUserByID(db *gorm.DB, id uint) (User, error) {
var user User
err := db.First(&user, id).Error
return user, err
}
查询所有数据:使用 Gorm,你可以使用 Find
函数查询记录。例如:
// GetAllUsers 查询所有用户
func GetAllUsers(db *gorm.DB) ([]User, error) {
var users []User
err := db.Find(&users).Error
return users, err
}
更新记录:使用 Gorm,你可以使用 Update
函数或者Save
函数更新记录。例如:
// UpdateUserName 更新用户名称
func UpdateUserName(db *gorm.DB, id uint, name string) error {
return db.Model(&User{}).Where("id = ?", id).Update("name", name).Error
}
删除记录:使用 Gorm,你可以使用 Delete
函数删除记录。例如:
// DeleteUser 删除用户
func DeleteUser(db *gorm.DB, id uint) error {
return db.Delete(&User{}, id).Error
}
当使用 Gorm 实现增删改查函数时,你可以在建立数据库连接的基础上调用这些函数。以下是一个示例代码,展示了如何调用上述的增删改查函数:
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)
// User gorm.Model 定义
type User struct {
ID uint `gorm:"primary_key"`
Name string `gorm:"size:255"`
Age int
}
func main() {
dsn := "root:123456@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(err)
}
fmt.Println("Connected to the database")
// 自动迁移数据库表结构
err = db.AutoMigrate(&User{})
if err != nil {
log.Fatal(err)
}
// 创建记录(插入数据)
err = CreateUser(db, "倾心1", 25)
if err != nil {
log.Fatal(err)
}
err = CreateUser(db, "倾心2", 25)
if err != nil {
log.Fatal(err)
}
// 查询单条数据
user, err := GetUserByID(db, 1)
if err != nil {
log.Fatal(err)
}
fmt.Println(user)
// 查询所有数据
users, err := GetAllUsers(db)
if err != nil {
log.Fatal(err)
}
fmt.Println("所有用户:")
for _, user := range users {
fmt.Println(user)
}
// 更新数据
err = UpdateUserName(db, 1, "倾心3")
if err != nil {
log.Fatal(err)
}
// 查询更新后的数据
user, err = GetUserByID(db, 1)
if err != nil {
log.Fatal(err)
}
fmt.Println(user)
// 删除记录
err = DeleteUser(db, 1)
if err != nil {
log.Fatal(err)
}
// 再次查询所有数据
users, err = GetAllUsers(db)
if err != nil {
log.Fatal(err)
}
fmt.Println("所有用户:")
for _, user := range users {
fmt.Println(user)
}
}
// CreateUser 创建用户
func CreateUser(db *gorm.DB, name string, age int) error {
user := User{
Name: name,
Age: age,
}
return db.Create(&user).Error
}
// GetUserByID 通过id查找用户
func GetUserByID(db *gorm.DB, id uint) (User, error) {
var user User
err := db.First(&user, id).Error
return user, err
}
// GetAllUsers 查询所有用户
func GetAllUsers(db *gorm.DB) ([]User, error) {
var users []User
err := db.Find(&users).Error
return users, err
}
// UpdateUserName 更新用户名称
func UpdateUserName(db *gorm.DB, id uint, name string) error {
return db.Model(&User{}).Where("id = ?", id).Update("name", name).Error
}
// DeleteUser 删除用户
func DeleteUser(db *gorm.DB, id uint) error {
return db.Delete(&User{}, id).Error
}
运行结果:
这个示例代码定义了一个 User
结构体来映射数据库表。在 main
函数中,它首先建立与数据库的连接,然后使用 db.AutoMigrate
函数自动迁移数据库表结构。接下来,它调用 CreateUser
函数创建二个用户,先使用GetUserByID
查询id为1的用户打印结果,然后又使用 GetAllUsers
函数查询所有用户并打印结果。然后,它使用 UpdateUserName
函数更新用户名称,然后又使用GetUserByID
函数查询更新后的数据信息,并使用 DeleteUser
函数删除用户。最后,它再次查询所有用户并打印结果。
你可以根据自己的需求和实际数据库连接信息,修改代码中的数据库连接字符串以及执行的增删改查操作。更多的需求可见 https://gorm.io/zh_CN/docs/
文档学习进行操作。
Scanner 和 Valuer 是 Gorm 库中的接口,用于自定义类型在与数据库进行数据读取和写入时的行为。
Scan
方法,接收一个 interface{}
参数,用于接收数据库的值。type JSON json.RawMessage
// 实现 sql.Scanner 接口,Scan 将 value 扫描至 Jsonb
func (j *JSON) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
}
result := json.RawMessage{}
err := json.Unmarshal(bytes, &result)
*j = JSON(result)
return err
}
Value
方法,返回一个 driver.Value
类型的值,用于表示数据库可以接受的数据。type JSON json.RawMessage
// 实现 driver.Valuer 接口,Value 返回 json value
func (j JSON) Value() (driver.Value, error) {
if len(j) == 0 {
return nil, nil
}
return json.RawMessage(j).MarshalJSON()
}
总的来说,Scanner 和 Valuer 接口提供了一种灵活的方式,允许你在 Gorm 中自定义数据类型的读写行为,以满足特定的需求,例如自定义数据类型的数据库映射、复杂类型的序列化和反序列化,以及数据库字段的加密和解密等场景。
下面是一个示例代码,演示了如何在 Gorm 中使用 Scanner 和 Valuer 接口进行自定义类型的读写行为:
package main
import (
"database/sql/driver"
"fmt"
"log"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type CustomData struct {
Data string
}
func (cd *CustomData) Scan(value interface{}) error {
// 从数据库的值中解析数据并存储到自定义类型中
if v, ok := value.([]byte); ok {
cd.Data = string(v)
}
return nil
}
func (cd CustomData) Value() (driver.Value, error) {
// 将自定义类型的值转换为数据库可以接受的形式
return []byte(cd.Data), nil
}
type User struct {
ID uint `gorm:"primary_key"`
Name string `gorm:"size:255"`
Data CustomData `gorm:"type:text"`
}
func main() {
dsn := "root:123456@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 {
log.Fatal(err)
}
// 自动迁移数据库表结构
err = db.AutoMigrate(&User{})
if err != nil {
log.Fatal(err)
}
// 创建记录
user := User{
Name: "John Doe",
Data: CustomData{Data: "Some data"},
}
err = db.Create(&user).Error
if err != nil {
log.Fatal(err)
}
// 查询记录
var retrievedUser User
err = db.First(&retrievedUser, user.ID).Error
if err != nil {
log.Fatal(err)
}
fmt.Println(retrievedUser)
// 更新记录
err = db.Model(&retrievedUser).Update("Data", CustomData{Data: "Updated data"}).Error
if err != nil {
log.Fatal(err)
}
// 再次查询记录
var updatedUser User
err = db.First(&updatedUser, user.ID).Error
if err != nil {
log.Fatal(err)
}
fmt.Println(updatedUser)
// 删除记录
err = db.Delete(&updatedUser).Error
if err != nil {
log.Fatal(err)
}
fmt.Println("操作完成")
}
在此示例中,我们定义了一个名为 CustomData
的自定义类型,并实现了 Scanner
和 Valuer
接口的方法。然后我们定义了一个 User
结构体,其中包含一个 Data
字段,类型为 CustomData
。我们使用 Gorm 进行数据库操作,包括创建记录、查询记录、更新记录和删除记录。通过实现 Scanner
和 Valuer
接口,我们可以自定义 CustomData
类型的读写行为,并将其与 Gorm 一起使用。
在上述示例中,我们使用 “mysql” 方言和连接字符串来连接 MySQL 数据库。连接字符串的格式根据不同的数据库和驱动而有所不同,你需要替换示例中的 username
、password
和 database_name
为你实际的数据库连接信息。
在 GORM 中,可以使用 Begin
方法开始一个事务,然后使用 Commit
方法提交事务,或者使用 Rollback
方法回滚事务。下面是一个使用 GORM 进行事务操作的示例代码:
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)
type User struct {
ID uint `gorm:"primary_key"`
Name string `gorm:"size:255"`
Age int
}
func main() {
dsn := "root:123456@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 {
log.Fatal(err)
}
fmt.Println("Connected to the database")
// 开始事务
tx := db.Begin()
// 创建记录(插入数据)
err = CreateUser(tx, "倾心", 25)
if err != nil {
// 回滚事务
tx.Rollback()
log.Fatal(err)
}
// 查询记录
user, err := GetUserByID(tx, 1)
if err != nil {
// 回滚事务
tx.Rollback()
log.Fatal(err)
}
fmt.Println(user)
// 提交事务
err = tx.Commit().Error
if err != nil {
log.Fatal(err)
}
// 查询所有数据
users, err := GetAllUsers(db)
if err != nil {
log.Fatal(err)
}
fmt.Println("所有用户:")
for _, user := range users {
fmt.Println(user)
}
}
// CreateUser 创建用户
func CreateUser(db *gorm.DB, name string, age int) error {
user := User{
Name: name,
Age: age,
}
return db.Create(&user).Error
}
// GetUserByID 通过id查找用户
func GetUserByID(db *gorm.DB, id uint) (User, error) {
var user User
err := db.First(&user, id).Error
return user, err
}
// GetAllUsers 查询所有用户
func GetAllUsers(db *gorm.DB) ([]User, error) {
var users []User
err := db.Find(&users).Error
return users, err
}
在上面的示例中,我们使用 Begin
方法开始了一个事务,并将事务对象赋值给 tx
变量。然后,我们在事务中执行了插入数据的操作,并在查询数据时使用了事务。如果在事务执行过程中发生错误,我们调用 Rollback
方法回滚事务。如果一切正常,我们调用 Commit
方法提交事务。
事务可以确保一系列数据库操作要么全部成功提交,要么全部回滚。这样可以保持数据的一致性。在实际应用中,事务经常用于处理复杂的数据操作,确保数据的完整性和一致性。
如果本篇文章对你有用,欢迎点赞转发关注本 倾心全栈成长录
公众号,一起交流学习进步。相关的代码资料公众号发送关键字 gorm