Go开源宝藏GORM 专场 (含思维导图) | 持续更新
Posted 小生凡一
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go开源宝藏GORM 专场 (含思维导图) | 持续更新相关的知识,希望对你有一定的参考价值。
写在前面
本人只是一个Go语言的
初学者
,这篇文只是把我平常经常用到的都总结起来而已。
具体详细的内容建议到去GORM的中文文档
查看。
当然这篇文章也会持续更新
,记录我的CURD打磨过程
这篇文章也会持续更新哒
思维导图
1. 简介
- 介绍:一个Go语言开发的ORM库,是
字节
的一位大牛写哒!!国产框架! - 下载:
go get -u github.com/jinzhu/gorm
流程:
- 导入Gorm
- 导入数据库驱动
- 定义数据库模型
- 与数据库连接
- 字段迁移映射
- 增、删、改、查
- 关闭数据库连接
2. 数据库驱动
数据库 | 驱动 | 导入 |
---|---|---|
mysql | github.com/go-sql-driver/mysql | github.com/jinzhu/gorm/dialects/mysql |
postgresql | github.com/lib/pq | github.com/jinzhu/gorm/dialects/postgres |
sqlite | github.com/mattn/go-sqlite3 | github.com/jinzhu/gorm/dialects/sqlite |
sqlserver | github.com/jinzhu/gorm/dialects/mssql |
3. 连接(MySQL为例子)
配置ini
文件
[mysql]
Db = mysql
DbHost = 127.0.0.1
DbPort = 3306
DbUser = root
DbPassWord = root
DbName = carsys
读取配置文件
file, err := ini.Load("./conf/config.ini")
if err != nil {
fmt.Println("配置文件读取错误,请检查文件路径:", err)
}
LoadMysqlData(file)
数据库路径拼接
path := strings.Join([]string{DbUser, ":", DbPassWord, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8&parseTime=true"}, "") // 路径拼接
model.Database(path) // 连接数据库
连接
数据库,这个是放在了model包,所以后面的操作都是model.DB
的
var DB *gorm.DB //全局的数据库入口
func Database(connString string) {
db, err := gorm.Open("mysql", connString)
db.LogMode(true)
if err != nil {
panic(err)
}
if gin.Mode() == "release" {
db.LogMode(false)
}
db.SingularTable(true) //默认不加复数s,不然他的每个数据后面都会加上和s比如user变成users
db.DB().SetMaxIdleConns(20) //设置连接池,空闲
db.DB().SetMaxOpenConns(100) //设置打开最大连接
db.DB().SetConnMaxLifetime(time.Second * 30)
DB = db
migration() //模型迁移映射到数据库
}
4. 迁移(MySQL为例子)
自动迁移数据库到最新版本,最会添加列和索引,不会
修改类型
和删除列
4.1 构建数据库表
这个gorm.Model
是自动加上create_time
,update_time
,delete_time
。
查看源码里面得gorm
中得model
。
然后我们可以像这样直接去定义一个struct
模型,准备映射到数据库中,就不用写sql
语句了。
后面可以加上tag
就像是gorm:"unique"
这样的,表示这个是唯一的。
import "github.com/jinzhu/gorm"
type User struct {
gorm.Model
UserName string `gorm:"unique"`
Email string
PasswordDigest string
Nickname string `gorm:"unique"`
Status string
Limit int // 0 非管理员 1 管理员
Type int // 0表示用户 1表示商家
Avatar string `gorm:"size:1000"`
Monery int
}
4.2 数据库模型迁移
gorm提供了一个AutoMigrate
的方法,很方便地进行映射迁移的工作。
func migration() {
//自动迁移模式
DB.Set("gorm:table_options", "charset=utf8mb4").
AutoMigrate(&User{})
}
4.3 tags束缚
4.3.1 一对多
语义场景:评论和帖子的关系。一个帖子有很多的评论,但是这个评论只能在这个帖子下面。
所以可以通过foreignkey
进行外键的束缚。外键到Social
这个模型。关系标识为social_id
。
type Comment struct {
gorm.Model
Content string
ParentId uint // 父评论ID
UserID uint // 用户ID
ReplyName string // 回复者名字
UserName string
UserAvatar string
SocialId uint `gorm:"foreignkey:Social;association_jointable_foreignkey:social_id"` //社区帖子ID
Children []Comment `gorm:"foreignkey:ParentId"`
}
4.3.2 多对多
语义环境:一个用户可以有多个好友,反过来也可以。所以就是user表自己的多对多。
使用tags是many2many
type User struct {
gorm.Model
Relations []User `gorm:"many2many:relation; association_jointable_foreignkey:relation_id"`
UserName string
Email string //`gorm:"unique"`
Avatar string `gorm:"size:1000"`
Phone string
BanTime int
OpenID string `gorm:"unique"`
}
这样的多对多的关联,就会多创建一个表来存两者的关系。
5. 增
5.1 一对一
create
函数进行创建。
category := model.Category{
CategoryName: service.CategoryName,
EnglishName:service.EnglishName,
}
err := model.DB.Create(&category).Error
5.2 一对多
语义环境:这里就是一评论表,socialId就是帖子, 一个帖子对应多个评论,和一对一是 一样的创建方式
var comment model.Comment
comment = model.Comment{
UserID: user.ID,
Content: service.Content,
ParentId: service.ParentId,
UserName: user.UserName,
UserAvatar: user.Avatar,
SocialId: service.SocialID,
}
err := model.DB.Create(&comment).Error
5.3 多对多
语义环境:用户表,用户和用户之间建立多对多联系
type User struct {
gorm.Model
Relations []User `gorm:"many2many:relation; association_jointable_foreignkey:relation_id"`
UserName string
Email string //`gorm:"unique"`
Avatar string `gorm:"size:1000"`
Phone string
BanTime int
OpenID string `gorm:"unique"`
}
选出user表中的两个元素。然后进行关联绑定。
var user model.User
var friend model.User
model.DB.Model(&friend).Where(`id = ? `,id).First(&friend) //被关注者
model.DB.Model(&user).Where(`id = ?`,userId).First(&user) //关注者
err := model.DB.Model(&user).Association(`Relations`).Append([]model.User{friend}).Error
这条语句就是把这个user
和这个friend
建立联系,存放在Relations
表里面。
6. 删
6.1 一对一
GORM中的delete
删除是软删除,就是虽然是删除了,但是并没有完全删除,而是保留在数据中但是查询并不查询这条已经删除的语句。
- 单记录删除
先找到这条数据
var social model.Society
code := e.Success
err := model.DB.First(&social, id).Error // 根据id找到这个social,记得传地址。
然后进行删除即可
err = model.DB.Delete(&social).Error
- 批量删除
db.Where("user_name like ? ","%Fan%").Delete(User{})
- 永久删除:在数据库直接清空了,不是软删除了
db.Unscoped().Where("name Like ?","%6%").Delete(User{})
6.2 一对多
其实
一对一
就是特殊的一对多
。
删除和一对一其实是一样的操作。
var social model.Society
model.DB.First(&social, id) // 找到这个帖子
model.DB.Delete(&social) // 将其进行删除
6.3 多对多
找到这两者的关系,然后进行关联删除
即可。就会从Relations表中把这两者的关系进行删除。
var user model.User
var friend []model.User
model.DB.Model(&friend).Where(`id = ?`,id).First(&friend) //被关注者
model.DB.Model(&user).Where(`id = ?`,userId).First(&user) //关注者
err := model.DB.Model(&user).Association(`Relations`).Delete(friend).Error
7. 改
7.1 一对一
- Save
会保存所有的字段,即使字段是零值
social := model.Society{
CategoryID: service.CategoryID,
Title: service.Title,
Content: service.Content,
Picture: service.Picture,
CategoryName: service.CategoryName,
}
err := model.DB.Save(&social).Error
- Update
当使用Update
更新单个列时,需要指定条件,否则会返回ErrMissingWhereClause
错误。
model.DB.Model(model.User{}).Where("open_id=?", openid).Update("phone", phone)
- Updates
批量更新,只会更新指定字段,但是如果是
空值
的情况下是不更新
的成空值的。
只更新指定字段
model.DB.Table("user").Where("user_name = ?","FanOne").
Updates(map[string]interface{}{"phone":"10001","email":"fanone@qq.com"})
只更新更改的
和非零值的
字段
model.DB.Model(&User{}).Where("user_name = ?","FanOne").
Updates(User{Phone:"10001",Email:"fanone@666.com"})
7.2 一对多
直接更新字段,同上。
7.3 多对多
由于多对多的是根据关系
来关联的,所以更新字段
和关系
是无关的,同上。
8. 查
First
是找到第一个Last
是找到最后一个Find
是找到全部
8.1 一对一
语义环境:用户表
type User struct {
gorm.Model
Relations []User `gorm:"many2many:relation; association_jointable_foreignkey:relation_id"`
UserName string
Email string //`gorm:"unique"`
Avatar string `gorm:"size:1000"`
Phone string
BanTime int
OpenID string `gorm:"unique"`
}
8.1.1 基本查询
- 查询第一个
var u1 User
db.First(&u1)
fmt.Println(u1)
- 查询最后一个
var u2 User
db.Last(&u2)
fmt.Println(u2)
- 按主键获取
var u3 User
db.First(&u3,2) //不指定的话,默认主键是id
fmt.Println(u3)
- 按条件查询一条
var u4 User
db.First(&u4,"user_name=?","FanOne") //不指定的话,默认主键是id
fmt.Println(u4)
- 获取所有数据
var u5 []User
db.Find(&u5) //查询所有的数据信息
fmt.Println(u5)
8.1.2 Where条件
- 单一条件
var u1 User
db.Where("user_name = ?","FanOne").First(&u1)
- 嵌套查询
var u1s []User
db.Where("user_name=?","fanone").Where("phone=?","10086").Find(&u1s)
- 多条件
var u2 User
db.Where("user_name = ? AND phone = ?","FanOne","10086").First(&u2)
- 模糊查询 记得加上
%
var u3 User
db.Where("user_name LIKE ?","%Fan%").First(&u3) //返回第一个user_name与Fan相近的数据
var u3s []User
db.Where("user_name LIKE ?","%Fan%").Find(&u3) //返回多个user_name与Fan相近的数据
- 范围查询
var u4 []User
db.Where("id > ?","FanOne","10").Find(&u2) // 找到id>10那部分的数据
- 数组形式
var u5 []User
db.Where("user_name in (?)",[]string{"Fan","One"}).Find(&u5)
- 结构体形式
var u6 User
db.Where(&User{UserName:"FanOne"}).First(&u6)
- map形式
var u7 User
db.Where(map[string]interface{}{"user_name":"fan","phone":"10086"}).First(&u7)
8.1.3 Not条件
- 查询UserName != FanOne的数据,返回列表
var u1 []User
db.Not(&User{UserName:"FanOne"}).Find(&u1)
- 查询UserName != FanOne的数据,返回第一条数据
var u2 User
db.Not("user_name","FanOne").First(&u2)
- 查询UserName != fan的数据,返回第一条数据
var u3 User
db.Not("user_name = ?","fan").First(&u2)
- 查询 UserName 不在这个字符串列表当中的数据,返回第一条数据
var u4 User
db.Not("user_name",[]string{"fan","one"}).First(&u4)
- 查询 UserName 不在这个字符串列表当中的数据,返回列表
var u5 []User
db.Not("user_name in (?)",[]string{"fan","one"}).Find(&u5)
8.1.4 选择查询
- 只查询user_name这一列的数据
var u1 []User
db.Select("user_name").Find(&u1)
- 只查询user_name和phone这两列的数据,字符串数组形式
var u1 []User
db.Select([]string{"user_name","phone"}).Find(&u1)
- 只查询user_name和phone这两列的数据,字符串数组形式
var u1 []User
db.Select("user_name , phone").Find(&u1)
8.1.5 排序
默认排序是升序的
var u1s,u2s []User
db.Order("name desc").Find(&u1s) //按照名字降序
db.Order("name asc",true).Find(&u1s) //按照名字升序
8.1.6 分页
Limit
页面大小
Offset
页数
var us []User
db.Order("id asc").Offset(5).Limit(3).Find(&us)
8.1.7 数量
var count int
db.Model(&User{}).Count(&count)
var count int
db.Model(&User{}).Where("user_name Like ?","%6%").Count(&count)
var count int
db.Table("users").Where("user_name Like ?","%6%").Count(&count)
8.1.8 原生SQL
当我们要进行比较复杂的查询的时候,可以通过这个原生sql进行查询。进行并查询
操作
query := "SELECT * FROM `work_time` WHERE `work_time`.`deleted_at` IS NULL AND month = "+ `"`+ data.Month +`"`
if data.Search!="" {
query += ` AND (( mask LIKE "`+"%"+data.Search +"%"+ `" ) OR ( number LIKE "`+"%"+data.Search+"%"+ `" ))`
}
if data.DepartmentName!="" {
query += " AND department_name LIKE " + `"`+"%" +data.DepartmentName+"%" + `"`
}
if data.WorkType!="" {
query += " AND work_type LIKE " + `"`+"%" +data.WorkType+"%" + `"`
}
if data.EmployeeStatus!="" {
query += " AND employee_status LIKE " + 以上是关于Go开源宝藏GORM 专场 (含思维导图) | 持续更新的主要内容,如果未能解决你的问题,请参考以下文章