GORM
这部分暂时不是重点,会基础CRUD即可
什么是gorm
The fantastic ORM library for Golang aims to be developer friendly.
就是一个go语言ORM(Object Relational Mapping)框架
通过ORM,我们可以把对象映射到关系型数据库中,实现无需编写原生sql就能操作关系型数据库
我们直接上手操作就行
gorm基础
安装
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite
模型定义
type Student struct {
Id int `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` //column指定在数据库中对应的字段
Name string `gorm:"column:name" json:"name"`
Sex string `gorm:"column:sex" json:"sex"`
Age string `gorm:"column:age" json:"age"`
}
GORM 倾向于约定优于配置:
默认情况下,GORM 使用
ID作为主键,使用结构体名的蛇形复数作为表名,字段名的蛇形作为列名,并使用CreatedAt、UpdatedAt字段追踪创建、更新时间gorm提供了一个gorm.Model结构体,其包括字段
ID、CreatedAt、UpdatedAt、DeletedAt,我们可以直接把它嵌入我们的结构体我们可以使用tag来控制字段,详见官方文档
需要注意的是,在gorm中,表名默认是结构体名的复数,列名默认是字段名的蛇形小写。比如上述结构体,gorm会认为表名是studnets,那如何解决这个问题呢?只需要在init的时候加一句db.SingularTable(true)
或者在查询时临时指定表名
连接到数据库
GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server
连接到MySQL:
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "student:pass@tcp(127.0.0.1:3306)/school?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}
GORM 允许通过一个现有的数据库连接来初始化 *gorm.DB,例如:
import (
"database/sql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var db *gorm.DB
func initDB() {
var err error
dsn := "student:pass@tcp(127.0.0.1:3306)/school?charset=utf8mb4&parseTime=True&loc=Local"
//dsn := dsn.DSN
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Println(err)
}
db.SingularTable(true)
log.Println("connect success:")
}
CRUD
这部分多看官方文档,很详细
插入:
func insert(st model.Student) {
res := db.Table("student").Create(&st)
if res.Error != nil {
log.Println("insert err:", res.Error)
}
log.Println("insert success")
}
用指定的字段创建记录
创建记录并更新给出的字段。
db.Select("Name", "Age", "CreatedAt").Create(&st)
// INSERT INTO `students` (`name`,`age`,`created_at`) VALUES ("王", 18, "2020-07-04 11:05:21.775")
创建一个记录且一同忽略传递给略去的字段值。
db.Omit("Name", "Age", "CreatedAt").Create(&st)
// INSERT INTO `students` (`birthday`,`updated_at`) VALUES ("2020-01-01 00:00:00.000", "2020-07-04 11:05:21.775")
批量插入
要有效地插入大量记录,请将一个
slice传递给Create方法。 GORM 将生成单独一条SQL语句来插入所有数据,并回填主键的值,钩子方法也会被调用。
var sts = []model.student{{Name: "王1"}, {Name: "王2"}, {Name: "王3"}}
db.Create(&st)
for _, st := range sts {
st.Id // 1,2,3
}
使用 CreateInBatches 分批创建时,你可以指定每批的数量,例如:
var students = []student{{name: "王_1"}, ...., {Name: "王_10000"}}
// 数量为 100
db.CreateInBatches(students, 100)
查询:
st := model.Student{}
//查询第一条记录
db.First(&st)
log.Println("success find:", st)
//如果主键是数字类型,可以使用内联条件检索
db.First(&st, 10)
// SELECT * FROM student WHERE id = 10;
db.First(&st, "10")
// SELECT * FROM student WHERE id = 10;
db.Find(&st, []int{1, 2, 3})
// SELECT * FROM student WHERE id IN (1,2,3);
//如果主键是字符串(例如像 uuid),查询将被写成这样:
//db.First(&st, "id = ?", "1b74413f-f3b8-409f-ac47-e8c062e3472a")
// SELECT * FROM student WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";
//当目标对象有一个主要值时,将使用主键构建条件,例如:
st.Id = 1
db.First(&st)
st = model.Student{}
// SELECT * FROM student WHERE id = 10;
var result model.Student
db.Model(model.Student{Id: 10}).First(&result)
// SELECT * FROM student WHERE id = 10;
//检索全部记录
var sts []model.Student
db.Find(&sts)
//随机获取一条记录
db.Take(&st)
log.Println("success take:", st)
//获取最后一条记录
db.Last(&st)
log.Println("success last:", st)
//条件查询:
// 获取第一条匹配的记录
db.Where("name = ?", "王").First(&st)
// SELECT * FROM student WHERE name = '王' ORDER BY id LIMIT 1;
// 获取所有匹配的记录
db.Where("name <> ?", "王").Find(&st)
// SELECT * FROM student WHERE name <> '王';
// IN
db.Where("name IN ?", []string{"王", "王 2"}).Find(&st)
// SELECT * FROM student WHERE name IN ('王','王 2');
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&st)
// SELECT * FROM student WHERE name LIKE '%jin%';
// AND
db.Where("name = ? AND age >= ?", "王", "22").Find(&st)
// SELECT * FROM student WHERE name = '王' AND age >= 22;
// Time
db.Where("updated_at > ?", lastWeek).Find(&st)
// SELECT * FROM student WHERE updated_at > '2000-01-01 00:00:00';
// BETWEEN
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&st)
// SELECT * FROM student WHERE created_at BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';
//当然,也可以使用原生sql进行扫描
var st model.student
db.Raw("SELECT id, name, ag,sex FROM student WHERE name = ?", 3).Scan(&st)
更新:
//----`Save` 会保存所有的字段,即使字段是零值
db.First(&st)
student.Name = "wang"
student.Age = 12
db.Save(&st)
// UPDATE students SET name='王 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;
//----更新单个列
// 条件更新
db.Model(&model.Student{}).Where("active = ?", true).Update("name", "hello")
// UPDATE students SET name='hello', updated_at='2013-11-17 21:34:10' WHERE active=true;
// student 的 ID 是 `111`
db.Model(&model.Student{}).Update("name", "hello")
// UPDATE students SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
// 根据条件和 model 的值进行更新
db.Model(&model.Student{}).Where("active = ?", true).Update("name", "hello")
// UPDATE students SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true
//----更新多个列
// 根据 `struct` 更新属性,只会更新非零值的字段
db.Model(&st).Updates(model.student{Name: "hello", Age: 18, Active: false})
// UPDATE students SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
// 根据 `map` 更新属性
db.Model(&st).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE students SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
//----更新选定字段
// 使用 Map 进行 Select
// student's ID is `111`:
db.Model(&st).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE students SET name='hello' WHERE id=111;
db.Model(&st).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE students SET age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
// 使用 Struct 进行 Select(会 select 零值的字段)
db.Model(&st).Select("Name", "Age").Updates(model.student{Name: "new_name", Age: 0})
// UPDATE students SET name='new_name', age=0 WHERE id=111;
// Select 所有字段(查询包括零值字段的所有字段)
db.Model(&st).Select("*").Update(model.student{Name: "jin", Role: "admin", Age: 0})
// Select 除 Role 外的所有字段(包括零值字段的所有字段)
db.Model(&st).Select("*").Omit("Role").Update(model.student{Name: "jin", Role: "admin", Age: 0})
删除:
st:= model.Student{Id:10}
db.Delete(&st)
// DELETE from student where id = 10;
// 带额外条件的删除
db.Where("name = ?", "王").Delete(&st)
// DELETE from student where id = 10 AND name = "王";