Go GORM实战(一) | 简单的增删改查

GORM是一个非常优秀的Golang数据库ORM库,支持MySQL, PostgreSQL, SQlite, SQL Server等数据库

database/sql

database/sql库是Go内置的用于操作数据库的标准库,在使用Go开发需要操作数据库的项目时,在不引入第三方库的情况下,可以完成对数据库的操作 

package main

import (
	"database/sql"
	"fmt"
)

/*
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    age INT NOT NULL
);
*/
import (
	_ "github.com/go-sql-driver/mysql" //驱动
)

// 操作数据库的对象
var db *sql.DB

// User 数据表模型
type User struct {
	ID   int
	Name string
	Age  int
}

func main() {
	var err error
	//打开数据库连接
	db, err = sql.Open("mysql", "root:123qwe@tcp(localhost:3306)/mysql_db?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	//验证连接
	if err = db.Ping(); err != nil {
		panic(err)
	}
	defer db.Close() //关闭数据库

	if Insert(&User{Name: "aaaaaa", Age: 20}) > 0 {
		fmt.Println("用户写入成功")
	}
	if Insert(&User{Name: "bbbbbb", Age: 21}) > 0 {
		fmt.Println("用户写入成功")
	}

	//查询全表数据
	uSlice := QueryAll()
	for _, us := range uSlice {
		fmt.Println(us.ID, us.Name, us.Age)
	}

	//查询单条数据
	u := QueryOne(uSlice[0].ID)
	if u != nil {
		fmt.Println(u.ID, u.Name, u.Age)
	}

	//更新
	if Update(&User{ID: uSlice[0].ID, Name: "cccccc", Age: 30}) > 0 {
		fmt.Printf("用户%v信息更新成功\n", uSlice[0].ID)
	}

	if user := QueryOne(uSlice[0].ID); user != nil {
		fmt.Println(user.ID, user.Name, user.Age)
	}

	//删除
	if Delete(uSlice[0].ID) {
		fmt.Printf("用户%v删除成功\n", uSlice[0].ID)
	}
	if Delete(uSlice[1].ID) {
		fmt.Printf("用户%v删除成功\n", uSlice[1].ID)
	}
	fmt.Println(QueryOne(uSlice[0].ID))
	fmt.Println(QueryOne(uSlice[1].ID))
}

func QueryAll() []*User {
	rows, _ := db.Query("SELECT * FROM users")
	defer rows.Close()
	var users []*User
	for rows.Next() {
		var user = &User{}
		err := rows.Scan(&user.ID, &user.Name, &user.Age)
		if err != nil {
			panic(err)
		}
		users = append(users, user) //放到User指针切片
	}
	return users
}

func QueryOne(id int) *User {
	rows, _ := db.Query("SELECT * FROM users WHERE id = ?", id)
	defer rows.Close() //避免资源泄露
	var user *User
	for rows.Next() {
		user = &User{}
		// 将结果扫描到结构体中
		err := rows.Scan(&user.ID, &user.Name, &user.Age)
		if err != nil {
			panic(err)
		}
	}
	return user
}

func Delete(id int) bool {
	//删
	rsDelete, err := db.Exec("DELETE FROM users WHERE id = ?", id)
	if err != nil {
		return false
	}
	n, err := rsDelete.RowsAffected()
	if err != nil {
		return false
	}
	return n > 0
}

func Update(user *User) int64 {
	//改
	rsUpdate, err := db.Exec("UPDATE users SET name = ?,age = ? WHERE id = ?", user.Name, user.Age, user.ID)
	if err != nil {
		return 0
	}
	n, err := rsUpdate.RowsAffected()
	if err != nil {
		return 0
	}
	return n
}

func Insert(user *User) int64 {
	//增
	rsInsert, err := db.Exec("INSERT INTO users values(?,?,?)", user.ID, user.Name, user.Age)

	if err != nil {
		return 0
	}
	n, err := rsInsert.RowsAffected() //执行 SQL 语句后影响的行数
	if err != nil {
		return 0
	}
	return n
}

使用database/sql标准库操作数据库有两个缺点:

  1. 不能将模型映对为数据表的操作,需要自己写SQL语句

  2. 不能将查询结果集映射到数据模型中,需要自己遍历

对于小项目来说,全部自己写SQL和自己遍历查询结果集,也是可以接受的,但如果是大项目的话,上面两个问题会导致项目越来越难维护。

这时候,使用ORM库可以帮我们完美解决上述的问题,而GORM无疑是首选

GORM 

GORM是一个对Go开发者非常友好的ORM库,上手非常简单,在GORM的官网文档上,我们可以看见其列出了GORM的以下特性:

  • 关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)

  • Create,Save,Update,Delete,Find 中钩子方法

  • 支持 Preload、Joins 的预加载

  • 事务,嵌套事务,Save Point,Rollback To Saved Point

  • Context、预编译模式、DryRun 模式

  • 批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD

  • SQL 构建器,Upsert,数据库锁,Optimizer/Index/Comment Hint,命名参数,子查询

  • 复合主键,索引,约束

  • Auto Migration

  • 自定义 Logger

  • 灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…

安装gorm库 

go get -u gorm.io/gorm

安装对应数据库的驱动  

# sqlite
go get -u gorm.io/driver/sqlite

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

# postgres
go get -u gorm.io/driver/postgres

# sqlserver
go get -u gorm.io/driver/sqlserver

 驱动层才是直接帮我们去访问的数据库的地方,而gorm库和database/sql这两个库只是在驱动层之上再封装一层,提供统一访问层,这样之后如果我们想更换数据库,比如从mysql切换到sqlserver,只需要改下引入的驱动库,而不是修改任何操作数据库的代码,访问层、驱动层与数据库

package main

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

/*
CREATE TABLE users (
	id INT AUTO_INCREMENT PRIMARY KEY,
	name VARCHAR(255) NOT NULL,
	age INT NOT NULL
);
*/

type User struct {
	ID   int
	Name string
	Age  int
}

func main() {
	dsn := "root:123qwe@tcp(127.0.0.1:3306)/mysql_db?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //打开数据库连接
	if err != nil {
		panic(err)
	}
	DB, err := db.DB()
	if err != nil {
		panic(err)
	}
	defer DB.Close() //在函数执行完成后关闭数据库句柄

	//新增
	rsOne := db.Create(&User{Name: "aaaaaaaaaa", Age: 30})
	if rsOne.RowsAffected > 0 {
		fmt.Println("用户创建成功")
	}

	rsTwo := db.Create(&User{Name: "bbbbbbbbbb", Age: 32})
	if rsTwo.RowsAffected > 0 {
		fmt.Println("用户创建成功")
	}

	//批量查询
	var users []User
	db.Find(&users)
	for _, user := range users {
		fmt.Println(user)
	}

	//查询
	var u User
	db.Find(&u, "id = ?", users[0].ID)
	fmt.Println(u)

	//修改
	u.Name = "2222222222"
	rsSave := db.Save(u)
	if rsSave.RowsAffected > 0 {
		fmt.Println("用户修改成功")
	}
	//修改后查询数据是否已经变化
	db.Find(&u, "id = ?", users[0].ID)
	fmt.Println(u)

	//删除
	rsDelete := db.Delete(u)
	if rsDelete.RowsAffected > 0 {
		fmt.Printf("用户%v删除成功\n", u.ID)
	}
	//删除
	user := db.Delete(users[1])
	if user.RowsAffected > 0 {
		fmt.Printf("用户%v删除成功\n", users[1].ID)
	}
}

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于 GORM,一对多关系通常是通过外键来实现的。下面是一对多关系的增删改查示例: 1. 增加数据: 假设有两个模型:User 和 Article,一个用户可以拥有多篇文章。 ```go type User struct { gorm.Model Name string Articles []Article } type Article struct { gorm.Model Title string Content string UserID uint // 外键 } // 创建用户和文章 user := User{Name: "John"} article1 := Article{Title: "Article 1", Content: "Content 1"} article2 := Article{Title: "Article 2", Content: "Content 2"} // 关联文章到用户 user.Articles = []Article{article1, article2} // 创建用户和关联的文章到数据库 db.Create(&user) ``` 2. 查询数据: ```go var user User db.Preload("Articles").First(&user, 1) // 根据用户ID查询用户及关联的所有文章 // 输出用户信息及关联的文章 fmt.Println("User:", user.Name) for _, article := range user.Articles { fmt.Println("Article:", article.Title) } ``` 3. 修改数据: ```go // 查询用户 var user User db.First(&user, 1) // 根据用户ID查询用户 // 修改用户的一篇文章 user.Articles[0].Title = "Updated Title" // 更新数据库中的数据 db.Save(&user) ``` 4. 删除数据: ```go // 查询用户 var user User db.First(&user, 1) // 根据用户ID查询用户 // 删除用户的一篇文章 article := user.Articles[0] db.Delete(&article) ``` 以上是简单的示例,实际使用中可以根据具体需求进行适当修改。注意在实际开发中,需要根据业务需求来处理级联操作、删除约束等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值