Gorm入门 | 青训营

81 阅读4分钟

Gorm 是一个go语言ORM(Object Relational Mapping)框架。

通过ORM,我们可以把对象映射到关系型数据库中,实现无需编写原生sql就能操作关系型数据库。

Gorm基础

安装

go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite

模型定义

GORM 倾向于约定优于配置:

  • 默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAtUpdatedAt 字段追踪创建、更新时间
  • gorm提供了一个gorm.Model结构体,其包括字段 IDCreatedAtUpdatedAtDeletedAt,我们可以直接把它嵌入我们的结构体
  • 我们可以使用tag来控制字段,详见官方文档
  • 需要注意的是,在gorm中,表名默认是结构体名的复数,列名默认是字段名的蛇形小写。比如上述结构体,gorm会认为表名是studnets,那如何解决这个问题呢?只需要在init的时候加一句db.SingularTable(true)或者在查询时临时指定表名
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 官方支持的数据库类型有: 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
}

查询:

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);

	//当目标对象有一个主要值时,将使用主键构建条件,例如:
	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';

更新:

/----`Save` 会保存所有的字段,即使字段是零值
db.First(&st)

student.Name = "xiaoming"
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;

删除:

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 = "小明";

总结

Gorm 是开发者强大的工具,加以利用能够节省大量写重复sql语句的时间。

参考

Gorm官方文档: GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.