GORM的学习笔记
GORM是开发Golang后端服务与关系型数据库交互的首选库,它几乎包含了你可能想到的所有跟数据库交互的功能,而且有非常完善且易懂的文档,以及庞大的社区。在使用过程中遇到任何问题,都可以很容易地获得解决方案。
这篇笔记文章会记录一下我初学GORM,实践基本的增删改查功能的过程。
数据库安装
这里多亏了1024code提供的数据库资源,可以很方便的在代码空间里绑定一个关系型数据库。并且数据库连接需要的信息都已经在环境变量中设置好了。
连接数据库
在我的Go项目中,我编辑了 main.go 文件:
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
"os"
)
func main() {
dbUser := os.Getenv("MYSQL_USER")
Pass := os.Getenv("MYSQL_PASSWORD")
Host := os.Getenv("MYSQL_HOST")
Port := os.Getenv("MYSQL_PORT")
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/mysql?charset=utf8mb4&parseTime=True&loc=Local", dbUser, Pass, Host, Port)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("DB connection failed.")
}
}
说明:
- 导入了相关的库。
- 在主函数中,首选通过
os库从环境变量中获取数据库连接所需的信息,然后根据dsn的格式将这些信息插入,用这个dsn进行数据库连接 - 如果报错,我们就返回一个
panic。否则,我们后面就可以用db来进行数据库交互了。
定义模型
因为刚好大项目也需要一个用户表单,我们就以此为例,定义一个User模型结构体:
type User struct {
ID uint `gorm:"primarykey"`
Username string `gorm:"unique"`
Password string
}
其中,ID是主键。Username是用户名,设置为unique,也就是不能有重复的用户名。Password是密码,这里就简单的使用明文字符串。生产环境中我们应当使用更加复杂、安全的方式对用户的密码进行加密。
定义好模型之后,要记得将定义好的模型转换为数据库中的表单:
db.AutoMigrate(&User{})
现在我们来通过命令行连接一下MySQL数据库,验证一下表单有没有正确创建。
~/app$ mysql -h ${MYSQL_HOST} -P ${MYSQL_PORT} -u ${MYSQL_USER} -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1028
Server version: 8.0.30 MySQL Community Server - GPL
可以看到我们已经成功连上了MySQL数据库。
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> describe users;
+----------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-----------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| username | varchar(191) | YES | UNI | NULL | |
| password | longtext | YES | | NULL | |
+----------+-----------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
可以看到现在数据库已经成功创建了名为mysql.users的表单(gorm会自动匹配MySQL的命名要求,用小写字母且复数单词)。其中的字段也是和我们的定义一一对应的。
实现增删改查
添加数据
我们添加一个名为Bob的用户,然后通过GORM在数据库中创建这条记录。
user := User{Username: "Bob", Password: "bobpassword"}
result := db.Create(&user)
if result.Error != nil {
panic("Failed to insert data.")
}
在MySQL中验证一下结果:
mysql> select * from users;
+----+----------+-------------+
| id | username | password |
+----+----------+-------------+
| 1 | Bob | bobpassword |
+----+----------+-------------+
1 row in set (0.00 sec)
可以看到我们成功地创建了这条数据。
查找数据
我们先给数据库中多添加几条数据,然后用GORM对他们进行查询。
我们用上面的方法将下面的用户数据添加到了数据库中:
var users = []User{
{Username: "Alice", Password: "alice123"},
{Username: "Charlie", Password: "charlie456"},
{Username: "David", Password: "david789"},
{Username: "Eva", Password: "eva101112"},
{Username: "Frank", Password: "frank131415"},
}
然后现在我对这些数据进行查询。这里我们尽可能的使用了多种不同的查询条件和方法。
-
按用户名查询:查询用户名为"Alice"的用户。
var userAlice User db.Where("username = ?", "Alice").First(&userAlice) fmt.Println(userAlice)得到:
{2 Alice alice123} -
查询密码长度大于8的用户:这里我们使用SQL函数**
LENGTH**。var usersWithLongPassword []User db.Where("LENGTH(password) > ?", 8).Find(&usersWithLongPassword) for _, user := range usersWithLongPassword { fmt.Println(user) }得到:
{1 Bob bobpassword} {3 Charlie charlie456} {5 Eva eva101112} {6 Frank frank131415} -
模糊查询:查询用户名中包含字母"a"的用户。
var usersWithA []User db.Where("username LIKE ?", "%a%").Find(&usersWithA) for _, user := range usersWithA { fmt.Println(user) }得到:
{2 Alice alice123} {3 Charlie charlie456} {4 David david789} {5 Eva eva101112} {6 Frank frank131415} -
排序并取前两个:按用户名升序排序,取前两个用户。
var firstTwoUsers []User db.Order("username ASC").Limit(2).Find(&firstTwoUsers) for _, user := range firstTwoUsers { fmt.Println(user) }得到:
{2 Alice alice123} {1 Bob bobpassword} -
偏移与限制:跳过第一个用户,取接下来的两个用户。
var twoUsersAfterFirst []User db.Offset(1).Limit(2).Find(&twoUsersAfterFirst) for _, user := range twoUsersAfterFirst { fmt.Println(user) }得到:
{2 Alice alice123} {3 Charlie charlie456} -
统计查询:查询总用户数。
var count int64 db.Model(&User{}).Count(&count) fmt.Printf("Total number of users: %d\n", count)得到:
Total number of users: 6
更新数据
这里我们尝试将用户Alice的密码修改掉:
userToUpdate := User{}
err := db.Where("username = ?", "Alice").First(&userToUpdate).Error
if err != nil {
fmt.Println("Error finding user:", err)
return
}
userToUpdate.Password = "AliceNewPassword"
db.Save(&userToUpdate)
可以看到在数据库中密码已经变成了AliceNewPassword
mysql> select * from users where username = "Alice";
+----+----------+------------------+
| id | username | password |
+----+----------+------------------+
| 2 | Alice | AliceNewPassword |
+----+----------+------------------+
1 row in set (0.00 sec)
删除数据
这里我尝试将密码长度小于10位的用户删除:
db.Where("LENGTH(password) < ?", 10).Delete(&User{})
可以看到用户David和Eva被删掉了:
mysql> select * from mysql.users;
+----+----------+------------------+
| id | username | password |
+----+----------+------------------+
| 1 | Bob | bobpassword |
| 2 | Alice | AliceNewPassword |
| 3 | Charlie | charlie456 |
| 6 | Frank | frank131415 |
+----+----------+------------------+
4 rows in set (0.00 sec)