gorm的使用
1. 地址
功能
2. 下载方式
go get -u gorm.io/gorm // gorm框架
go get -u github.com/go-sql-driver/mysql // mysql驱动
3. 连接数据库
package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"net/url"
"time"
)
var DB *gorm.DB
func InitDatabase() *gorm.DB {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name
args := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=true&loc=%s",
"root", //数据库的账号
"123456", // 数据库的密码
"localhost", // 数据的IP地址
"3306", // 数据的端口
"test", // 使用的数据库
"utf8", // 编码格式
url.QueryEscape(""))
fmt.Println("args", args)
db, err := gorm.Open("mysql", args)
if err != nil {
panic("failed to connect database, err: " + err.Error())
}
DB = db
return db
}
func main() {
InitDatabase()
}
4. 开始建立模型类
模型是标准的 struct,由 Go 的基本数据类型、实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成(从官网抄的)
4.1 字段类型
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
// 转成的sql语句
/* CREATE TABLE `users` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`age` tinyint unsigned DEFAULT NULL,
`birthday` datetime DEFAULT NULL,
`member_number` varchar(255) DEFAULT NULL,
`activated_at` datetime DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
*/
4.2 字段的约束
4.2.1 说明
标签名 | 说明 |
---|---|
column | db的列名 |
type | 列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如:not null 、size , autoIncrement … 像 varbinary(8) 这样指定数据库数据类型也是支持的。在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENT |
serializer | 指定将数据序列化或反序列化到数据库中的序列化器, 例如: serializer:json/gob/unixtime |
primaryKey | 将列定义为主键 |
unique | 将列定义为唯一键 |
default | 定义列的默认值 |
precision | 指定列的精度 |
scale | 指定列大小 |
not null | 指定列为 not null |
autoincrement | 指定列为自增长 |
autoIncrementIncrement | 自动步长,控制连续记录之间的间隔 |
embedded | 嵌套字段 |
embeddedPrefix | 嵌入字段的列名前缀 (发现没有效果) |
autoCreateTime | 创建时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,您可以使用 nano /milli 来追踪纳秒、毫秒时间戳,例如:autoCreateTime:nano |
autoUpdateTime | 创建/更新时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,您可以使用 nano /milli 来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milli |
index | 根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看 索引 获取详情 |
uniqueIndex | 与 index 相同,但创建的是唯一索引 |
check | 检查约束的类型,列入check:age>13, |
<- | 设置字段写入的权限, <-:create 只创建、<-:update 只更新、<-:false 无写入权限、<- 创建和更新权限 |
-> | 设置字段读的权限,->:false 无读权限 |
- | 忽略该字段,- 表示无读写,-:migration 表示无迁移权限,-:all 表示无读写迁移权限 |
comment | 迁移时为字段添加注释 |
4.2.2 具体实例
type User struct {
ID uint `gorm:"primaryKey;comment:'id'"`
Name string `gorm:"unique; comment:'用户的名字'; column:name"`
Email *string `gorm:"varchar(200);"`
Age uint8 `gorm:"default:18"`
Birthday *time.Time `gorm:"not null;"`
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
/*
生成的表
CREATE TABLE `users` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(255) DEFAULT NULL COMMENT '用户的名字',
`email` varchar(255) DEFAULT NULL,
`age` tinyint unsigned DEFAULT '18',
`birthday` datetime DEFAULT NULL,
`member_number` varchar(255) DEFAULT NULL,
`activated_at` datetime DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
*/
type Base struct {
Id uint `gorm:"primaryKey; comment:'id'; uniqueIndex; autoIncrement; autoIncrementIncrement:3; column:id"`
CreateTime *time.Time `gorm:"autoCreateTime; comment:'创建时间'"`
UpdateTime *time.Time `gorm:"autoUpdateTime; comment:'更新时间'"`
Test string
}
type Card struct {
Base Base `gorm:"embedded;embeddedPrefix:'card_'"`
Uid uint `gorm:"not null; comment:'用户id'; check:uid>0; column:user_id"`
}
/*
embeddedPrefix 好像没有效果
CREATE TABLE `cards` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`test` varchar(255) DEFAULT NULL,
`user_id` int unsigned NOT NULL COMMENT '用户id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
*/
5. 建立外键
5.1 一对一
5.1.1 创建结构体
type User struct {
ID uint `gorm:"primaryKey;comment:'id'"`
Name string `gorm:"unique; comment:'用户的名字'; column:name"`
Email *string `gorm:"varchar(200);"`
Age uint8 `gorm:"default:18"`
Birthday *time.Time `gorm:"not null;"`
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
CardId Card
Card Card
}
type Base struct {
Id uint `gorm:"primaryKey; comment:'id'; uniqueIndex; autoIncrement; autoIncrementIncrement:3; column:id"`
CreateTime *time.Time `gorm:"autoCreateTime; comment:'创建时间'"`
UpdateTime *time.Time `gorm:"autoUpdateTime; comment:'更新时间'"`
Test string
}
type Card struct {
Base Base `gorm:"embedded;embeddedPrefix:'card_'ti"`
Uid uint `gorm:"not null; comment:'用户id'; check:uid>0; column:user_id"`
}
5.1.2 保存数据
func inUser(db *gorm.DB) {
/*
@desc: 插入数据到user表里面
@auth: alex
@data: 11/6/22
@params db *gorm.DB
*/
email := "alexxu@qq.com"
layoutISO := "2006-01-02"
date := "2000-08-24"
birthDay, _ := time.Parse(layoutISO, date)
user := User{
Name: "alex",
Email: &email,
Age: 3,
Birthday: &birthDay,
MemberNumber: struct {
String string
Valid bool
}{String: "13096575416", Valid: true},
ActivatedAt: struct {
Time time.Time
Valid bool
}{Time: time.Now(), Valid: true},
Card: Card{Base: Base{Test: "hello world"}},
}
db.Debug().Omit("Card").Create(&user)
db.Save(&user)
user1 := User{
Name: "alex1",
Email: &email,
Age: 3,
Birthday: &birthDay,
MemberNumber: struct {
String string
Valid bool
}{String: "13096575416", Valid: true},
ActivatedAt: struct {
Time time.Time
Valid bool
}{Time: time.Now(), Valid: true},
Card: Card{Base: Base{Test: "hello world"}},
}
db.Debug().Omit("Card").Create(&user1)
db.Save(&user1)
}
5.1.3 查询数据
5.1.3.1 正向查询
func FindUser(db *gorm.DB) {
/*
@desc: /*
@auth: alex
@data: 11/6/22
@params db gorm.DB
*/
var user User
var card Card
db.Model(&user).Where(map[string]interface{}{"ID": 1}).First(&user).Association("Card").Find(&card)
fmt.Println("card", card.Base.Test)
}
5.1.3.2 反向查询
func FindUser(db *gorm.DB) {
/*
@desc: /*
@auth: alex
@data: 11/6/22
@params db gorm.DB
*/
var user User
var card Card
db.Model(&card).Where(map[string]interface{}{"Id": 1}).Preloads("Card").Find(&user)
fmt.Println("user", user)
}
5.2一对多
5.2.1 创建结构体
type User struct {
ID uint `gorm:"primaryKey;comment:'id'"`
Name string `gorm:"unique; comment:'用户的名字'; column:name"`
Email *string `gorm:"varchar(200);"`
Age uint8 `gorm:"default:18"`
Birthday *time.Time `gorm:"not null;"`
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
CardId uint
Card Card
ClassId uint `gorm:"comment:'班级id';"`
}
type Card struct {
Base Base `gorm:"embedded;embeddedPrefix:'card_'"`
}
type Class struct {
Base // 班级
User []User `gorm:"foreignKey:ClassId;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` // 将数据存在CLassId里面
}
5.2.2 保存数据
func inUser(db *gorm.DB) {
/*
@desc: /*
@auth: alex
@data: 11/8/22
@params db *gorm.DB
*/
email := "alexxu@qq.com"
layoutISO := "2006-01-02"
date := "2000-08-24"
birthDay, _ := time.Parse(layoutISO, date)
class := Class{
User: []User{User{
Name: "alex",
Email: &email,
Age: 3,
Birthday: &birthDay,
MemberNumber: struct {
String string
Valid bool
}{String: "13096575416", Valid: true},
ActivatedAt: struct {
Time time.Time
Valid bool
}{Time: time.Now(), Valid: true},
Card: Card{Base: Base{Test: "hello world"}},
}},
}
db.Debug().Create(&class)
}
5.2.3查询数据
5.2.3.1正向查询
func findUser(db *gorm.DB) {
user := []User{}
class := Class{}
a := db.Where(map[string]interface{}{
"Id": 1,
}).Find(&class).Association("User").Find(&user)
fmt.Println("a", a)
fmt.Println("class", len(user))
}
5.2.3.2 反向查询
func findUser(db *gorm.DB) {
// 反向查询
user := User{}
class := Class{}
db.Model(&class).Where(map[string]interface{}{
"Id": 1,
}).Preloads("User").Find(&user)
fmt.Println("user", user.ID)
}
5.3 多对多
5.3.1 创建结构体
type User struct {
ID uint `gorm:"primaryKey;comment:'id'"`
Name string `gorm:"unique; comment:'用户的名字'; column:name"`
Email *string `gorm:"varchar(200);"`
Age uint8 `gorm:"default:18"`
Birthday *time.Time `gorm:"not null;"`
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
CardId uint
Card Card
ClassId uint `gorm:"comment:'班级id';"`
Happy []Happy `gorm:"many2many:user_happy"` // 为了插入数据的时候方便
}
type Happy struct {
// 兴趣
Base
Name string `gorm:"comment:'兴趣'; not null; unique;"`
User []User `gorm:"many2many:user_happy"` //user_happy是表名
}
5.3.2 保存数据
5.3.2.1在happy里面插入数据
func inHappy(db *gorm.DB) {
happySlice := make([]Happy, 0)
happySlice = append(happySlice, Happy{Name: "唱歌"})
happySlice = append(happySlice, Happy{Name: "旅游"})
happySlice = append(happySlice, Happy{Name: "跳舞"})
for index := 0; index < len(happySlice); index++ {
db.Save(&happySlice[index])
}
}
5.3.2.2将user和happy绑定在一起
func inUser(db *gorm.DB) {
// 开始插入数据
user := User{} // 用户
happySlice := make([]Happy, 0) // 用户的兴趣
db.Where(map[string]interface{}{
"id": 1,
}).Find(&user)
db.Where([]uint{1, 2}).Find(&happySlice)
// 不知道为什么,只更新Happy的话是不会更新的,所以我加了一个Name字段
db.Debug().Model(&user).Updates(User{Happy: happySlice, Name: user.Name})
}
5.4 查询数据
func findUser(db *gorm.DB) {
user := User{}
happySlice := make([]Happy, 0)
// 直接在后面用associationd,只有where条件在happy表也会存在
db.Model(&user).Where(map[string]interface{}{
"Id": 1,
}).Find(&user)
db.Model(&user).Association("Happy").Find(&happySlice)
for index := 0; index < len(happySlice); index++ {
fmt.Println("happy", happySlice[index].Name)
}
}
结束了,谢谢大家可以看到现在。如果有哪里写的不好,大家可以指出来,然后我再去修改,希望大家可以提出宝贵的意见
这里是我的微信,如果有需要的话,大家可以扫码添加我好友