Grom学习之路
一、orm的背景
1、作用
(1)通过操作结构体对象,来达到操作数据库表的目的;
(2)通过结构体对象,来生成数据库表;
2、优点:
3、为什么使用:
不同的程序员书写的sql语句的执行效率不同,所以使用orm可以统一操作方法(类似linq)。
4、注意事项
grom支持mysql和redis等,xrom支持mysql,redis和oracle;如果需要操作oracle请使用xrom;因为grom只能对表进行操作,所以需要搭配sql语句来;
二、grom的连接数据库,建表
1、创建数据库表结构
//模型结构
type Student struct {
Id int
Name string
Age int
}
//使用dsn连接到数据库,grom自带的数据库池
//账号:密码@连接方式(ip地址:端口号)/数据库?语言方式,时区(未设置时区的话采用8小时制度)
dsn := "root:root@tcp(127.0.0.1:3306)/testgorm?charset=utf8mb4&parseTime=True&loc=Local"
conn, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
if err != nil {
fmt.Println(err)
}
conn.AutoMigrate(&Student{}) //创建表?判断是否表结构存在
注意:导入驱动使用下划线的原因:驱动中使用init函数就可以进行底层链接的调用。
三、grom的链接池
1、conn.Close()不需要的原因就是conn就是一个链接池的句柄;
2、设置链接池的初始链接数和最大连接数目;
3、一般将链接池的句柄设置为全局变量,可以多处使用;
四、Grom的数据插入
1、结构体全字段属性插入
stu := &Student{
Id: 1,
Name: "yang",
Age: 22,
}
res := conn.Create(stu) //向数据库中插入数据
if res.Error != nil { //判断是否插入数据出错
fmt.Println(res.Error)
}
2、结构体部分字段属性插入
stu1 := &Student{
Id: 2,
Name: "xin",
}
res := conn.Select("Id", "Name").Create(stu1)
if res.Error != nil { //判断是否插入数据出错
fmt.Println(res.Error)
}
3、批量插入
stus := []Student{
{Name: "jun", Age: 24},
{Name: "zhou", Age: 26},
}
conn.Create(&stus)
五、Grom数据的查询
1、单条查询
user := new(Student) //实例化对象
res := db.First(&user) //将查询数据传入到对象中
fmt.Println(res.Error) //判断返回值的错误
fmt.Println(res.RowsAffected) //查看返回条数
fmt.Println("查询到的对象为", user)
同理可得:把first换成take为不讲究顺序的单挑查询
2、全部查询
dsn := "root:root@tcp(127.0.0.1:3306)/testgorm?charset=utf8mb4&parseTime=True&loc=Local"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
users := []Student{} //实例化对象
db.Find(&users) //将所有查询数据传入到对象中
fmt.Println(users) //打印所有数据
3、Where条件语句;
(1)通过占位符号可以像sql语句一样进行条件筛选
dsn := "root:root@tcp(127.0.0.1:3306)/testgorm?charset=utf8mb4&parseTime=True&loc=Local"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
user := new(Student)
db.Where("age=?", 2).First(&user)
fmt.Println(user)
// 获取第一条匹配的记录
db.Where("name = ?", "jinzhu").First(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
// 获取全部匹配的记录
db.Where("name <> ?", "jinzhu").Find(&users)
// SELECT * FROM users WHERE name <> 'jinzhu';
// IN
db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&users)
// SELECT * FROM users WHERE name IN ('jinzhu','jinzhu 2');
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
// SELECT * FROM users WHERE name LIKE '%jin%';
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
// Time
db.Where("updated_at > ?", lastWeek).Find(&users)
(2)通过结构体筛选
stu := new(Student)
db.Where(&Student{Name: "yang"}).Find(&stu) //通过结构体的Name查找
fmt.Println(stu)
stu := new(Student)
res := db.Where(&Student{Name: "yang"}, "age").Find(&stu) SELECT * FROM users WHERE name = "jinzhu" AND age = 0;
fmt.Println(res.Error)
fmt.Println(res.RowsAffected)
fmt.Println(stu)
//或者
db.Where(&User{Name: "jinzhu"}, "name", "Age").Find(&users)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 0;
(3)通过map查找
stu := new(Student)
res := db.Where(map[string]interface{}{"name": "yang", "age": 22}).Find(&stu) //查询name=yang,age=22的用户
fmt.Println(res.Error)
fmt.Println(res.RowsAffected)
fmt.Println(stu)
六、条件判断语句
1、Not
db.Not("name = ?", "jinzhu").First(&user)
// SELECT * FROM users WHERE NOT name = "jinzhu" ORDER BY id LIMIT 1;
// Not In
db.Not(map[string]interface{}{"name": []string{"jinzhu", "jinzhu 2"}}).Find(&users)
// SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");
// Struct
db.Not(User{Name: "jinzhu", Age: 18}).First(&user)
// SELECT * FROM users WHERE name <> "jinzhu" AND age <> 18 ORDER BY id LIMIT 1;
// 不在主键切片中的记录
db.Not([]int64{1,2,3}).First(&user)
// SELECT * FROM users WHERE id NOT IN (1,2,3) ORDER BY id LIMIT 1;
2、or语句
第一种
stus := []Student{}
res := db.Where("name=? or name=?", "yang", "zhou").Find(&stus) //查询name=yang,age=22的用户
fmt.Println(res.Error)
fmt.Println(res.RowsAffected)
fmt.Println(stus)
第二种
stus := []Student{}
res := db.Where("name=?", "yang").Or("name=?", "zhou").Find(&stus) //查询name=yang,age=22的用户
fmt.Println(res.Error)
fmt.Println(res.RowsAffected)
fmt.Println(stus)
3、降序排列
dsn := "root:root@tcp(127.0.0.1:3306)/testgorm?charset=utf8mb4&parseTime=True&loc=Local"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
stus := []Student{}
res := db.Order("id desc").Find(&stus) //查询name=yang,age=22的用户
fmt.Println(res.Error)
fmt.Println(res.RowsAffected)
fmt.Println(stus)
多条件排序
dsn := "root:root@tcp(127.0.0.1:3306)/testgorm?charset=utf8mb4&parseTime=True&loc=Local"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
stus := []Student{}
res := db.Order("id desc").Order("name").Find(&stus) //
fmt.Println(res.Error)
fmt.Println(res.RowsAffected)
fmt.Println(stus)
4、Limit & Offset
stus := []Student{}
res := db.Limit(3).Find(&stus) //只查询3条数据
fmt.Println(res.Error)
fmt.Println(res.RowsAffected)
fmt.Println(stus)
Offset查询偏移量
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
stus := []Student{}
res := db.Limit(3).Offset(1).Find(&stus) //跳过第一条后,查询3条数据
fmt.Println(res.Error)
fmt.Println(res.RowsAffected)
fmt.Println(stus)
5、Group & Having
type result struct {
Date time.Time
Total int
}
db.Model(&User{}).Select("name, sum(age) as total").Where("name LIKE ?", "group%").Group("name").First(&result)
// SELECT name, sum(age) as total FROM `users` WHERE name LIKE "group%" GROUP BY `name`
db.Model(&User{}).Select("name, sum(age) as total").Group("name").Having("name = ?", "group").Find(&result)
// SELECT name, sum(age) as total FROM `users` GROUP BY `name` HAVING name = "group"
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Rows()
for rows.Next() {
...
}
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Rows()
for rows.Next() {
...
}
6、Distinct
db.Distinct("name", "age").Order("name, age desc").Find(&results)
7、Joins 预加载
db.Joins("Company").Find(&users)
// SELECT `users`.`id`,`users`.`name`,`users`.`age`,`Company`.`id` AS `Company__id`,`Company`.`name` AS `Company__name` FROM `users` LEFT JOIN `companies` AS `Company` ON `users`.`company_id` = `Company`.`id`;
8、创建并查询
stu := Student{}
res := db.FirstOrCreate(&stu, Student{Name: "FirstorCreate"})
fmt.Println(res.Error)
fmt.Println(res.RowsAffected)
fmt.Println(stu)
七、Gorm的更新
1、save更新保留所有的字段
stu := Student{}
db.First(&stu)
stu.Age = 22
db.Save(&stu)
2、使用结构体调用Update方法
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
stu := Student{
Id: 1,
}
db.Model(&stu).Update("name", "yang")
stu := Student{
Id: 1,
}
db.Model(&stu).Where("age=?", 23).Update("name", "yang")
//修改id=1,age=23的name为yang
3、更新多列
stu := Student{
Id: 1,
}
db.Model(&stu).Updates(map[string]interface{}{"name": "yang", "age": 23})
八、Grom的删除
1、删除
物理删除:真正执行Delete
stu := Student{
Id: 8,
}
db.Delete(&stu) //删除id=8的数据
//或者
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";
2、软删除
定义:逻辑删除,不真正删除。不执行Delete。因为数据无价;
原理:创建表的时候,在表中添加一个删除字段,当需要删除时,更新“删除字段”,更新为:true;查询的时候判断删除字段是否为null即可,举例:淘宝删除图片和订单;
实现:封装到grom.model结构体中
type Student struct {
gorm.Model //封装了相关字段
Name string
Age int
}
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
db.AutoMigrate(&Student{}) //创建表?判断是否表结构存在
stu := Student{
Name: "yang",
}
res := db.Where("Name", "yang").Delete(&stu) //软删除Name为t2的数据
fmt.Println(res.Error)
查询时会忽略软删除的数据
dsn := "root:root@tcp(127.0.0.1:3306)/testgorm?charset=utf8mb4&parseTime=True&loc=Local"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
db.AutoMigrate(&Student{}) //创建表?判断是否表结构存在
stus := []Student{}
db.Find(&stus)
for _, v := range stus {
fmt.Println(v)
}
软删除数据的查看;
db.Unscoped().Find(&stus)
// SELECT * FROM users WHERE age = 20;
清空软删除的回收站进行物理删除;
db.Unscoped().Delete(&order)
// DELETE FROM orders WHERE id=10;
注意:软删除的时区需要设置,他的deletetime时间才能正确
九,Grom设置表的属性
type Student struct {
gorm.Model //封装了相关字段
Name string `gorm:"size:100;default:'xiaoming'"`
Age int
}
tag标签只有在第一次建表的时候有效,或者给表增加新字段的时候有效这样的修改才有效。
十、Grom的时间戳
但是Grom只有时间戳属性,如果需要使用,就是用type标签
如果看完对自己有所帮助,请点赞支持,谢谢大家