JetBrains Goland:解决同个package不同文件不能互相调用-CSDN博客
官方文档地址:GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.
此时操作的表的结构为:
注意:使用的结构体的名字与表名对应
main包下 连接.go文件,初始化数据库连接
package main
import (
"fmt"
"gorm.io/gorm/logger"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB *gorm.DB
func init() {
username := "root" //账号
password := "123456" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名
port := 3306 //数据库端口
Dbname := "gorm" //数据库名
timeout := "10s" //连接超时,10秒
// root:root@tcp(127.0.0.1:3306)/gorm?
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
panic("连接数据库失败, error=" + err.Error())
}
DB = db
// 连接成功
fmt.Println(db)
}
//type Student struct {
// ID uint `gorm:"size:10"`
// Name string `gorm:"size:16"`
// Age int `gorm:"size:3"`
// Email *string `gorm:"size:128"`
//}
//
//func main() {
// DB.AutoMigrate(&Student{})
//}
同一main包下,新建 单表插入.go
package main
type Student struct {
ID uint `gorm:"size:10"`
Name string `gorm:"size:16"`
Age int `gorm:"size:3"`
Email *string `gorm:"size:128"`
}
func main() {
//DB.AutoMigrate(&Student{})
email := "[email protected]"
//添加记录 结构实例化
s1 := Student{ //id自动创建
Name: "wang",
Age: 21,
Email: &email,
}
err := DB.Create(&s1).Error
if err != nil {
println(err)
}
}
运行后 可见studens表插入如下 记录
有两个地方需要注意
多表通过建立切片来进行多个记录的插入
多表
├─ 多记录插入.go
└─ 连接.go
多表插入.go
package main
type Student struct {
ID uint `gorm:"size:10"`
Name string `gorm:"size:16"`
Age int `gorm:"size:3"`
Email *string `gorm:"size:128"`
}
func main() {
//DB.AutoMigrate(&Student{})
email := "[email protected]"
//添加记录 结构实例化
s1 := Student{ //id自动创建
Name: "wang",
Age: 21,
Email: &email, //指针类型可以传null值,别的不传默认为空值
}
s2 := Student{ //id自动创建
Name: "wang2",
Age: 22,
Email: nil, //指针类型可以传null值,别的不传默认为空值
}
s := []*Student{ //通过切片形式来生成多条记录
&s1, &s2,
}
//s := []Student{
// s1, s2,
//}
err := DB.Create(s).Error
if err != nil {
println(err)
}
}
studens表
我们一般使用Take方法进行查询
// 获取第一条记录(主键升序)
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;
// 获取一条记录,没有指定排序字段
db.Take(&user)
// SELECT * FROM users LIMIT 1;
// 获取最后一条记录(主键降序)
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;
db.First(&user, 10)
// SELECT * FROM users WHERE id = 10;
db.First(&user, "10")
// SELECT * FROM users WHERE id = 10;
db.Find(&users, []int{1,2,3})
// SELECT * FROM users WHERE id IN (1,2,3);
Take的第二个参数,默认根据主键查询
DB.Take(&student, 2)
fmt.Println(student)
student = Student{} // 重新赋值
DB.Take(&student, "4")
fmt.Println(student)
根据struct进行主键查询
//主键查询
var student Student
student.ID = 1
DB.Take(&student)
fmt.Println(student)
同样使用Take方法,根据其他条件查询,使用?作为占位符,将查询内容放入,这里为查询age=22的记录
DB.Take(&student, "age=?", 22)
var student2 Student
affected := DB.Take(&student2, "age=?", 22).RowsAffected//获取查询的记录数
fmt.Println(student2, affected)
查询多条记录一般使用find方法,take只能获取一条记录,这里不再适用
//查询多条记录
var students []Student //首先创建切片
rowsAffected := DB.Find(&students).RowsAffected
fmt.Println(students, rowsAffected)
for _, s := range students {
fmt.Println(s)
marshal, _ := json.Marshal(s) //通过序列化可以读出指针所指的内容
fmt.Println(string(marshal))
}
//根据主键查询多条记录
DB.Find(&students, []int{1, 2})
//DB.Take(&students, []int{1, 3}) //take只能获取单条记录
//根据其他条件查询多条记录, 可以与其他条件查询 单条记录进行对比
DB.Find(&students, "age in ?", []int{21, 23}) //查询年龄为21和23岁的
// 获取第一个匹配的记录
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;
// 时间
db.Where("updated_at > ?", lastWeek).Find(&users)
// SELECT * FROM users WHERE updated_at > '2000-01-01 00:00:00';
// BETWEEN
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
// SELECT * FROM users WHERE created_at BETWEEN '上周时间' AND '今天时间';
用于单个记录的全字段更新
它会保存所有字段,即使零值也会保存
DB.Take(&stu, 3) //查询id为3的记录,将其转化为结构体实例
//fmt.Println(stu)
stu.Age = 18 //修改结构体内容
stu.Name = "sb"
DB.Save(&stu) //将结构体内容传回sql
Save是一个组合功能。如果save value不包含主键,它将执行Create,否则将执行Update(包含所有字段)。
//save的create模式
stu = Student{
12,//原本students表中没有id为12的数据
"wang",
26,
nil,
}
DB.Save(&stu)
INSERT INTO `students` (`name`,`age`,`email`,`id`) VALUES ('wang',26,NULL,12) ON DUPLICATE KEY UPDATE `name`=VALUES(`name`),`age`=VALUES(`age`),`email`=VALUES(`email`)
db.Save(&User{Name: "jinzhu", Age: 100})
// INSERT INTO `users` (`name`,`age`,`birthday`,`update_at`) VALUES ("jinzhu",100,"0000-00-00 00:00:00","0000-00-00 00:00:00")
db.Save(&User{ID: 1, Name: "jinzhu", Age: 100})
// UPDATE `users` SET `name`="jinzhu",`age`=100,`birthday`="0000-00-00 00:00:00",`update_at`="0000-00-00 00:00:
更新指定字段, 跟直接save效果一致,但执行的sql语句不一致
var student Student
DB.Take(&student)
student.Age = 21
// 全字段更新
DB.Select("age").Save(&student)
// UPDATE `students` SET `age`=21 WHERE `id` = 1
update方法
//批量更新多条记录,单列
var students []Student
newEmail := "[email protected]"
//这里查询如果使用其他条件可以参考前面的查询部分
DB.Find(&students, []int{3, 4, 5}).Update("email", newEmail)
//使用model方法进行单列的数据更新
DB.Model(&students).Where("name=?", "sb").Update("name", "大聪明")
//DB.Model(&Student{}).Where("name=?", "sb").Update("name", "小聪明")//这种也可以
students = []Student{} //清空students
//使用model方法根据主键进行单列数据更新
DB.Model(&Student{ID: 12}).Update("age", 100)
updates方法,内需要用结构体
如果是结构体,它默认不会更新零值
email := "[email protected]"
DB.Model(&Student{}).Where("age = ?", 21).Updates(Student{
Email: &email,
Gender: false, // 这个不会更新
})
// UPDATE `students` SET `email`='[email protected]' WHERE age = 21
//使用model方法进行多列数据更新
DB.Model(&Student{}).Where("name=?", "wang3").Updates(Student{Name: "帅哥", Age: 18})
UPDATE `students` SET `name`='帅哥',`age`=18 WHERE name='wang3'
如果要传零值,可以使用select或map,这里使用map来进行展示
DB.Model(&Student{}).Where("age = ?", 21).Updates(map[string]any{
"email": &email,
"gender": false,
})
//根据主键删除
DB.Delete(&Student{}, 1) //删除主键为1的记录
//删除id为1的记录
DB.Delete(&Student{ID: 1})
//删除id为5的记录
DB.Where("id=?", 5).Delete(&Student{})
//根据主键删除
DB.Delete(&Student{}, []int{1, 2}) //删除主键为1、2的记录
//使用其它条件进行删除,这里也是可以用于多条记录的删除
email := "[email protected]"
DB.Where("email=?", &email).Delete(&Student{})
//使用其他条件进行删除
DB.Where("email=?", "[email protected]").Delete(&Student{})
更加详细的使用内容见官方文档
官方文档地址:GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.