ORM(对象关系映射)将对象模型与关系型数据库之间的数据进行映射和交互,它允许开发者使用面向对象的方式来操作数据库,而无需直接编写SQL查询语句。
ORM的主要目标是提供一个抽象层,使开发者能够以面向对象的方式处理数据,同时隐藏底层数据库的细节,提高开发效率;通过使用ORM,开发者可以使用类、对象和方法来执行常见的数据库操作,如插入、更新、删除和查询数据。
一、Gorm简介
Gorm 是一个使用Go语言编写的ORM框架。它文档齐全,对开发者友好,支持主流数据库(今天主要是介绍Mysql的相关操作)。
优点:提高了开发效率
缺点:牺牲执行性能、牺牲灵活性、弱化SQL能力
二、模块安装
虽然 Gorm 本身是一个强大的 ORM 库,但它本身并不包含与特定数据库的驱动程序。相反,它依赖于外部的数据库驱动程序来实际连接和与数据库进行通信,所以我们不仅需要安装 Gorm 模块,也需要安装它的驱动程序 driver/sqlite
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite
三、连接数据库(Mysql)
连接mysql数据库代码如下,我们需要修改里面的 dsn 连接地址,根据自己实际情况修改,user是用户名,password是数据库密码,127.0.0.1:3306是数据库地址和端口,dbname是需要连接的数据库名称。
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"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println("db err:", err)
return err
}
}
Mysql 驱动程序也提供了一些高级配置,可以在初始化过程中使用,我们通过指定数据库的详细信息和配置选项来创建一个与数据库的连接,并返回一个 db 对象,用于执行各种数据库操作。这样我们就可以使用 Gorm 提供的便捷功能来管理和操作 MySQL 数据库,如创建表、插入数据和查询数据等。
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // DSN data source name
DefaultStringSize: 256, // string 类型字段的默认长度
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
}), &gorm.Config{})
四、简单操作(增删改查)
1、我们首先先创建一个数据库表模型
type User struct { // 表名
gorm.Model
Name string `json:"name"`
Age int64 `json:"age"`
Interest string `json:"interest"` // 兴趣
}
上面的代码我们创建了一个简单的用户信息表包含了用户名称、年龄和用户的兴趣爱好,注意上面除了刚才所列的信息之外还有个 gorm.Model ,这个是Grom为简化表字段,里面包含了一些通用的子段,如:id,CreatedAt(创建时间)、UpdatedAt(更新时间)、DeletedAt(删除时间),这样就简化了我们创表操作,具体如下:
type Model struct {
ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt DeletedAt `gorm:"index"`
}
2、迁移数据库
当我们数据库表新建完成后,我们就需要去迁移我们的数据库,让我们的代码自动变成一个完整的数据库表。
db.AutoMigrate(&User{})
如果需要迁移多个,直接在 &User{} 后面增加即可
db.AutoMigrate(&User{},&test{})
3、添加数据
在数据库创建完成后,我们就可以添加我们第一个数据了,我们可以使用 db.Create()的方法来操作
db.Create(&User{Name: "张三", Age: 18, Interest: "篮球"})
4、查询数据
在我们完成添加数据的操作后,我们可以进行查询操作来查看刚才所添加的数据
(1)简单查询
获取第一条记录,按主键排序
db.First(&user)
根据主键ID查找,我们需要查找ID为1的用户信息
db.First(&user, 1)
相关字段查找,查找name等于张三的用户
db.First(&user, "name=?", "张三")
获取所有记录
db.Find(&user)
(2)not 非条件查询
查找用户名不是张三的用户信息
db.Not("name", "张三").First(&user)
现在给一个用户名称列表,查找不在这个用户名称列表的用户信息
db.Not("name", []string{"张三", "李四"}).Find(&user)
现在给一个用户ID列表,查找不在这个用户ID列表的用户信息
db.Not([]int64{4, 5, 6}).First(&user)
(3)OR 或条件查询
现在需要查找用户名称为张三或者年龄为18的用户
db.Where("name=?", "张三").Or("age=?", 18).Find(&user)
查询出名字为"张三"或者年龄为18的用户,并将结果存储在user变量中
db.Where(User{Name: "张三"}).Or(User{Age: 18}).Find(&user)
(4)链式查询(且查询)
查询出名字为"张三"且年龄为18岁的用户
db.Where("name =?", "张三").Where("age=? ", 18).Find(&user)
(5)Order语句
从数据库中按照ID字段降序排列获取所有的用户,降序:desc 生序:asc
db.Debug().Order("id desc").Find(&user)
db.Order("age asc").Find(&user)
(6)limit分页
对查询出的结果进行分页,只显示10个数据
db.Limit(10).Find(&user)
(7)Offset
从数据库中获取符合条件的记录,并跳过前面3条记录
db.Offset(3).Find(&user)
(8)Count 和计算
统计查询结果的数量,并将结果存储在count变量中
var count int64
db.Debug().Find(&user).Count(&count)
(9)预加载
在数据过多的情况下,我们可以采用预加载操作,从数据库中获取符合条件的用户记录,并预先加载每个用户关联的Orders表的数据。这样,当后续访问User模型的Orders属性时,不需要再执行额外的查询操作,可以直接从预加载的数据中获取。这有助于提高查询效率和减少数据库访问次数。
db.Preload("Orders").Find(&user)
5、更新数据
更新张三用户的用户名为李四
db.Model(&User).Where("name","张三").Update("name","李四");
更新张三用户的年龄为20
db.Model(&User).Updates(User{Name:"张三",Age:20})
6、删除数据
根据主键ID删除
db.Delete(&user, 1)
从数据库中删除名字包含"李四"的用户记录。通过使用like操作符和模糊匹配,可以对用户名进行灵活的匹配和删除操作。
db.Where("name like ?", "%李四%").Delete(User{})
从数据库中删除名字包含"李四"的用户记录,并在执行过程中输出调试信息以帮助开发者进行调试和优化。通过使用like操作符和模糊匹配,可以对用户名进行灵活的匹配和删除操作。
db.Debug().Delete(User{}, "name like ?", "%李四%")
注意:如果模型有 DeletedAt 字段,将自动获得软删除功能! 在调用 Delete 时不会从数据库中永久删除,而是只将字段 DeletedAt 的值设置为当前时间。软删除的记录将在查询时被忽略。
使用 Unscoped 查找软删除的记录
db.Unscoped().Where("name=?","张三").Find(&user);
使用 Unscoped 永久删除记录
db.Unscoped().Delete(&user);