golang入门笔记—Gorm

文章目录

    • Gorm介绍
    • Gorm基本操作
    • gorm的model结构体的使用
    • 时间戳跟踪
    • 数据库的插入记录
    • 查询
    • 更新
    • 删除
    • Gen代码生成

Gorm介绍

Gorm是go语言编写的一个ORM框架,是中国人开发的框架(自豪)
golang入门笔记—Gorm_第1张图片
偷懒不写sql语句数据库操作神器

ORM的优缺点:
优点:
提高开发效率

缺点:
牺牲执行功能
牺牲灵活性
弱化SQL能力

Gorm基本操作

package main

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type UserInfo struct {
	Id     uint
	Name   string
	Gender string
	Hobby  string
}

func main() {
	db, err := gorm.Open("mysql", "root:*****@(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()

	//创建表 自动迁移 (把结构体和数据库表进行对应)
	db.AutoMigrate(&UserInfo{})

	//创建数据行
	u1 := UserInfo{Id: 1, Name: "zyj", Gender: "男", Hobby: "唱"}
	db.Create(&u1)
	//查询
	var u UserInfo
	db.First(&u)
	fmt.Println(u)
	//更新
	db.Model(&u).Update("hobby", "唱跳rap篮球")
	//删除
	db.Delete(&u) //将查询出来的第一条数据删除
}

gorm的model结构体的使用

为了方便模型定义,GORM内置了一个gorm.Model结构体。gorm.Model是一个包含了ID,CreatedAt,UpdateAt,DeleteAt四个字段的Golang结构体,可以把这个结构体嵌入到自己的模型中。

type Model struct {
	ID        uint `gorm:"primary_key"`
	CreatedAt time.Time
	UpdatedAt time.Time
	DeletedAt *time.Time `sql:"index"`
}

package main

import (
	"database/sql"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"time"
)

//数据库中的表名为数据库变量名的复数

type UserInfo struct {
	gorm.Model          //内嵌gorm.Model
	Id           string `gorm:"primary_key"`
	Name         string
	Age          sql.NullInt64 //零值类型
	Birthday     *time.Time    `gorm:"column:user_birth"` //创建时设置列名为user_birth
	Email        string        `gorm:"type:varchar(100);unique_index"`
	Role         string        `gorm:"size:255"`        //设置字段大小为255
	MemberNumber *string       `gorm:"unique;not null"` //设置会员号(member number)唯一并且不为空
	Num          int           `gorm:"AUTO_INCREMENT"`  //设置num为自增类型
	Address      string        `gorm:"index:addr"`      //给address字段创建名为addr的索引
	IgnoreMe     int           `gorm:"-"`               //忽略本字段
}

func main() {
	db, err := gorm.Open("mysql", "root:********@(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()

	gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
		return "prefix_" + defaultTableName
	} //所有gorm创建的表名统一加prefix_

	db.AutoMigrate(&UserInfo{})

	//使用UserInfo结构体创建一个名叫user的表
	db.Table("user").CreateTable(&UserInfo{})
}

package main

import (
	"fmt"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func main() {
	dsn := "root:********@(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		SkipDefaultTransaction:                   true, //关闭默认事务
		PrepareStmt:                              true, //缓存预编译语句
		DisableForeignKeyConstraintWhenMigrating: true, //迁移时禁用外键约束
	})
	if err != nil {
		fmt.Println(err)
	}
	sqldb, _ := db.DB()
	sqldb.SetConnMaxLifetime(10 * time.Second) //设置最大连接时间
	sqldb.SetMaxIdleConns(10)                  //设置池中空闲连接数的上限
	sqldb.SetMaxOpenConns(100)                 //限制最大连接数
}

时间戳跟踪

CreatedAt该字段记录初次创建记录的时间

db.Create(&user) // `CreatedAt`将会是当前时间

// 可以使用`Update`方法来改变`CreateAt`的值
db.Model(&user).Update("CreatedAt", time.Now())

UpdatedAt该字段的值将会是每次更新记录的时间。

db.Save(&user) // `UpdatedAt`将会是当前时间

db.Model(&user).Update("name", "jinzhu") // `UpdatedAt`将会是当前时间

DeletedAt:调用Delete删除该记录时,将会设置DeletedAt字段为当前时间,而不是直接将记录从数据库中删除。

数据库的插入记录

package main

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

//1.定义模型
type User struct {
	ID   int64
	Name string `gorm:"default:'zyj''"`
	Age  int64
}

func main() {
	//连接MySQL数据库
	db, err := gorm.Open("mysql", "root:*****@(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()
	//2.把模型与数据库表对应起来
	db.AutoMigrate(&User{})

	//3.创建
	u := User{
		Name: "zyj",
		Age:  18,
	}

	fmt.Println("数据库存不存在该主键对应的对象", db.NewRecord(&u))
	db.Create(&u)         //创建记录
	db.Debug().Create(&u) //会把对应操作的sql语句打印出来
	//注意,所有字段的零值,如:0、”“、false等都不会保存入数据库,而是使用对应的默认值
}

查询

// 根据主键查询第一条记录
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.Find(&users)
 SELECT * FROM users;

// 查询指定的某条记录(仅当主键为整型时可用)
db.First(&user, 10)
 SELECT * FROM users WHERE id = 10;

where条件查询

// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
 SELECT * FROM users WHERE name = 'jinzhu' limit 1;

// Get all matched records
db.Where("name = ?", "jinzhu").Find(&users)
 SELECT * FROM users WHERE name = 'jinzhu';

// <>
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)
 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 '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';

Struct&Map查询

// Struct
db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
 SELECT * FROM users WHERE name = "jinzhu" AND age = 20 LIMIT 1;

// Map
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
 SELECT * FROM users WHERE name = "jinzhu" AND age = 20;

// 主键的切片
db.Where([]int64{20, 21, 22}).Find(&users)
 SELECT * FROM users WHERE id IN (20, 21, 22);

Not条件

db.Not("name", "jinzhu").First(&user)
 SELECT * FROM users WHERE name <> "jinzhu" LIMIT 1;

// Not In
db.Not("name", []string{"jinzhu", "jinzhu 2"}).Find(&users)
 SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");

// Not In slice of primary keys
db.Not([]int64{1,2,3}).First(&user)
 SELECT * FROM users WHERE id NOT IN (1,2,3);

db.Not([]int64{}).First(&user)
 SELECT * FROM users;

// Plain SQL
db.Not("name = ?", "jinzhu").First(&user)
 SELECT * FROM users WHERE NOT(name = "jinzhu");

// Struct
db.Not(User{Name: "jinzhu"}).First(&user)
 SELECT * FROM users WHERE name <> "jinzhu";

选择字段查询

db.Select("name, age").Find(&users)
 SELECT name, age FROM users;

db.Select([]string{"name", "age"}).Find(&users)
 SELECT name, age FROM users;

db.Table("users").Select("COALESCE(age,?)", 42).Rows()
 SELECT COALESCE(age,'42') FROM users;

查询并排序

db.Order("age desc, name").Find(&users)
 SELECT * FROM users ORDER BY age desc, name;

// 多字段排序
db.Order("age desc").Order("name").Find(&users)
 SELECT * FROM users ORDER BY age desc, name;

// 覆盖排序
db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
 SELECT * FROM users ORDER BY age desc; (users1)
 SELECT * FROM users ORDER BY age; (users2)

更多查询参考网站:
参考网站

更新

更新所有字段

db.First(&user)

user.Name = "七米"
user.Age = 99
db.Save(&user)

条件更新

// 更新单个属性,如果它有变化
db.Model(&user).Update("name", "hello")
 UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;

// 根据给定的条件更新单个属性
db.Model(&user).Where("active = ?", true).Update("name", "hello")
 UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;

// 使用 map 更新多个属性,只会更新其中有变化的属性
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
 UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

// 使用 struct 更新多个属性,只会更新其中有变化且为非零值的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18})
 UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;

// 警告:当使用 struct 更新时,GORM只会更新那些非零值的字段
// 对于下面的操作,不会发生任何更新,"", 0, false 都是其类型的零值
db.Model(&user).Updates(User{Name: "", Age: 0, Active: false})

更新所选字段

db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
 UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;

db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
 UPDATE users SET age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

删除

// 删除现有记录
db.Delete(&email)
 DELETE from emails where id=10;

// 为删除 SQL 添加额外的 SQL 操作
db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)
 DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);

db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
 DELETE from emails where email LIKE "%jinzhu%";

db.Delete(Email{}, "email LIKE ?", "%jinzhu%")
 DELETE from emails where email LIKE "%jinzhu%";

软删除

db.Delete(&user)
 UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;

// 批量删除
db.Where("age = ?", 20).Delete(&User{})
 UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;

// 查询记录时会忽略被软删除的记录
db.Where("age = 20").Find(&user)
 SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;

// Unscoped 方法可以查询被软删除的记录
db.Unscoped().Where("age = 20").Find(&users)
 SELECT * FROM users WHERE age = 20;

物理删除

// Unscoped 方法可以物理删除记录
db.Unscoped().Delete(&order)
 DELETE FROM orders WHERE id=10;

Gen代码生成

go get -u gorm.io/gen@latest
package main

import (
	"sign-lottery/pkg/constants"
	"strings"

	"gorm.io/driver/mysql"
	"gorm.io/gen"
	"gorm.io/gorm"
)

const MysqlDSN = constants.MysqlDSN //mysql连接的dsn

func main() {
	//连接数据库
	db, err := gorm.Open(mysql.Open(MysqlDSN))
	if err != nil {
		panic(err)
	}

	//创建generator实例
	g := gen.NewGenerator(gen.Config{
		OutPath:        "dao/db",             //模型输出地址
		Mode:           gen.WithDefaultQuery, //WithDefaultQuery 生成默认查询结构体(作为全局变量使用), 即`Q`结构体和其字段(各表模型)
		FieldNullable:  true,                 // 表字段可为 null 值时, 对应结体字段使用指针类型
		FieldCoverable: false,
		/*表字段默认值与模型结构体字段零值不一致的字段, 在插入数据时需要赋值该字段值为零值的, 结构体字段须是指针类型才能成功, 即`FieldCoverable:true`配置下生成的结构体字段.
		因为在插入时遇到字段为零值的会被GORM赋予默认值. 如字段`age`表默认值为10, 即使你显式设置为0最后也会被GORM设为10提交.
		如果该字段没有上面提到的插入时赋零值的特殊需要, 则字段为非指针类型使用起来会比较方便.*/
		FieldSignable:     false, // 模型结构体字段的数字类型的符号表示是否与表字段的一致, `false`指示都用有符号类型
		FieldWithIndexTag: false, // 生成 gorm 标签的字段索引属性
		FieldWithTypeTag:  true,  // 生成 gorm 标签的字段类型属性
	})
	g.UseDB(db)

	// 自定义字段的数据类型
	dataMap := map[string]func(detailType string) (dataType string){
		"varchar": func(detailType string) (dataType string) {
			return "string"
		},
		"bigint": func(detailType string) (dataType string) {
			return "int64"
		},
		"int": func(detailType string) (dataType string) {
			return "int"
		},
		"double": func(detailType string) (dataType string) {
			return "float64"
		},
		"text": func(detailType string) (dataType string) {
			return "string"
		},
		"tinytext": func(detailType string) (dataType string) {
			return "string"
		},
	}

	g.WithDataTypeMap(dataMap)

	// 自定义模型结体字段的标签
	// 将特定字段名的 json 标签加上`string`属性,即 MarshalJSON 时该字段由数字类型转成字符串类型
	jsonField := gen.FieldJSONTagWithNS(func(columnName string) (tagContent string) {
		toStringField := `balance, `
		if strings.Contains(toStringField, columnName) {
			return columnName + ",string"
		}
		return columnName
	})
	// 将非默认字段名的字段定义为自动时间戳和软删除字段;
	// 自动时间戳默认字段名为:`updated_at`、`created_at, 表字段数据类型为: INT 或 DATETIME
	// 软删除默认字段名为:`deleted_at`, 表字段数据类型为: DATETIME
	autoUpdateTimeField := gen.FieldGORMTag("updated_time", "column:updated_at;type:int unsigned;autoUpdateTime")
	autoCreateTimeField := gen.FieldGORMTag("created_at", "column:created_at;type:int unsigned;autoCreateTime")
	softDeleteField := gen.FieldType("deleted_at", "soft_delete.DeletedAt")
	fieldOpts := []gen.ModelOpt{jsonField, autoCreateTimeField, autoUpdateTimeField, softDeleteField}
	// 创建全部模型文件, 并覆盖前面创建的同名模型
	g.GenerateAllTable(fieldOpts...)
	g.Execute()
}

你可能感兴趣的:(go语言,golang)