官方文档地址:官方文档,点击跳转
安装:
go get -u github.com/jinzhu/gorm
初始化
链接数据库
mysql
// 引入gorm及驱动包
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
db,db_err := gorm.Open("mysql","root:root@[tcp](localhost:3306)/gorm_proj?charset=utf8&parseTime=True&loc=Local")
if err!= nil{
panic(err)
}
defer db.Close() // 关闭连接
// loc=Local:表示根据本地时区走
// parseTime:处理time.Time
sqllite
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
type Product struct {
gorm.Model
Code string
Price uint
}
func main() {
db, err := gorm.Open("sqlite3", "test.db")
if err != nil {
panic("连接数据库失败")
}
defer db.Close()
// 自动迁移模式
db.AutoMigrate(&Product{})
// 创建
db.Create(&Product{Code: "L1212", Price: 1000})
// 读取
var product Product
db.First(&product, 1) // 查询id为1的product
db.First(&product, "code = ?", "L1212") // 查询code为l1212的product
// 更新 - 更新product的price为2000
db.Model(&product).Update("Price", 2000)
// 删除 - 删除product
db.Delete(&product)
}
数据表操作
创建表CreateTable
type User struct {
Id int
Name string
Age int
}
// 创建表
db.Table("user").CreateTable(&User{}) // 指定表名
db.CreateTable(&User{}) // 不指定表名,模型后面会加个s
删除表DropTable
db.DropTable(&User{}) // 使用模型名
db.DropTable("users") // 直接使用表名
db.DropTableIfExists(&User{}) // 先判断是否存在再删除,可以接受多个参数,模型和字符串都可以
检查是否存在HasTable
is_has := db.HasTable(&User{}) // 使用模型
is_has := db.HasTable("users") // 使用表名
fmt.Println(is_has)
数据库迁移AutoMigrate
AutoMigrate
仅仅会创建表,
添加缺少列和索引,
不会改变现有列的类型或删除未使用的列
db.AutoMigrate(&User{})
db.AutoMigrate(&User{}, &Product{}, &Order{})
// 创建表时添加表后缀
db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{})
增删改查
结构体:
type User struct{
Id int
Name string
Age int
}
增
db.Create(&User{Id:1,Name:"hallen",Age:18})
删
var user User
db.First(&user,1) // 默认使用id字段
db.Delete(&user)
改
var user User
db.First(&user,1) // 默认使用id字段
db.Model(&user).Update("age",20) // 这里的Model是查询出来的结构体对象user,不是模型
查
var user User
db.First(&user,1) // 默认使用id字段
fmt.Println(user)
db.First(&user,"name=?","hallen") // 查询指定字段
fmt.Println(user)
模型定义
一对一
- 属于:关系和外键在同一方,有关系的那一方属于另外一个模型
-
包含:关系和外键不在同一方,有关系的那一方包含另外一个有外键的模型
这个可以用面向对象的类来理解,父类与子类,
在这个场景中,就相当于UserProfile是User的子类,UserProfile继承了User, 儿子属于父亲,UserProfile属于User
属于
// UserProfile属于User,外键是在UserProfile模型,外键字段为:UId
type User struct {
Id int
Name string
Age int
Addr string
}
type UserProfile struct {
Id int
Pic string
CPic string
Phone string
User User `gorm:"ForeignKey:UId;AssociationForeignKey:Id"` // 关联关系
//UserID int // 默认关联字段为Id
UId int // uid
}
注:
// 外键默认使用UserID,如果不指定外键,则使用默认的外键字段,
// 默认关联ID,通过AssociationForeignKey指定关联字段
包含
// UserProfile 包含一个 User, 外键在User模型,外键字段为:PId
type User struct {
Id int
Name string
Age int
Addr string
PId int
}
type UserProfile struct {
Id int
Pic string
CPic string
Phone string
User User `gorm:"ForeignKey:PId;AssociationForeignKey:Id"` // 关联关系
}
一对多
type User2 struct {
Id int
Name string
Age int
Addr string
Articles []Article `gorm:"ForeignKey:UId;AssociationForeignKey:Id"`
}
type Article struct {
Id int
Title string
Content string
Desc string
// 外键
UId int
}
多对多
type Article2 struct {
AId int `gorm:"primary_key:true"`
Title string
Content string
Desc string
Tags []Tag `gorm:"many2many:Article2s2Tags"` // ;ForeignKey:AId;AssociationForeignKey:TId
}
type Tag struct {
TId int `gorm:"primary_key:true"`
Name string
Desc string
}
一对一操作
增
user_profile := relate_tables.UserProfile{
Pic:"1.jpg",CPic:"2.jpg",Phone:"18241253695",
User:relate_tables.User{Name:"xiaosheng",Age:18,Addr:"lndg"},
}
result := db.Create(&user_profile)
默认是关联创建或更新的
创建/更新时不会保存关联:`gorm:"save_associations:false"`
查
Association
// 先查询出来,在根据Association属性值关联查询,Association的值为关联表的模型名称
var us models.UserProfile
DB.First(&us, 11)
// 查询不到,在执行下面关联查询会报错空指针
if us.User.Name == "" {
fmt.Println("没有找到")
return
}
// Association("User")中User是关联表的名字 例子中关联的是UserProfile
DB.Model(&us).Association("User").Find(&us.User)
fmt.Println(us)
Preload
var us models.UserProfile
// 查询不到不报错
DB.Debug().Preload("User").First(&us, 11)
fmt.Println(us)
Related
var us models.UserProfile
DB.First(&us, 111)
// 不能用同一个模型,需要额外构建一个
var user models.User
// 一定不要这样弄反了,看函数签名 DB.Model(&user).Related(&us.User, "User")
DB.Model(&us).Related(&user, "User")
fmt.Println(user)
更新
// 先关联查询出来,再更新关联表中的字段
us := new(models.UserProfile)
fmt.Printf("%T\n", us)
DB.Preload("User").First(us, 112)
fmt.Println(*us)
DB.Model(us).Update("Phone", "18889999999999")
删
var us models.UserProfile
DB.Preload("User").First(&us, 134)
//DB.Delete(&us)
// 删掉关联表中一条,是根据134查询出来关联表的id 24,然后才删除
DB.Debug().Delete(&us.User)
//DELETE FROM `users` WHERE `users`.`id` = 24
一对多操作
增
user := models.User2{
Name: "tomt",
Age: 10,
Addr: "tianjin",
Articles: []models.Article{{
Title: "Title",
Content: "Content",
Desc: "Desc",
}, {
Title: "Title",
Content: "Content1",
Desc: "Desc1",
},
},
}
ret := DB.Create(&user)
fmt.Println(ret.RowsAffected)
fmt.Println(ret.Error)
查
// 查询数据Preload
func query3() {
var user models.User2
DB.Preload("Articles").Find(&user, 1)
fmt.Println(user)
}
// 查询数据Find
func query4(){
var user models.User2
DB.First(&user,1)
DB.Model(&user).Association("Articles").Find(&user.Articles)
fmt.Println(user)
}
// 查询数据Related
func query5(){
var user models.User2
DB.First(&user, 1)
var articles []models.Article
DB.Model(&user).Related(&articles, "Articles")
fmt.Println(articles)
}
更新
var user models.User2
DB.First(&user, 1)
fmt.Println(user)
DB.Model(&user).Update("Name", "tom")
fmt.Println(user)
删
// 先查询数据
var user models.User2
DB.Preload("Articles").Find(&user, 1)
DB.Where("uid=?", 1).Delete(&user.Articles)
多对多操作
增
// 多对多 插入数据
func insertm2(){
articles2 := models.Article2{
//ID: `0j`,
Title: "title3",
Desc: "sssssssssssssssssssss",
Content: "ssssssssssssssssssssssssssssssssssssss",
Tags: []models.Tag{
{Name: "golang", Desc: "golang"},
{Name: "go", Desc: "go"},
},
}
DB.Create(&articles2)
}
func insert2(){
tags := models.Tag{Name: "golang", Desc: "golang"}
DB.Create(&tags)
articles := models.Article2{
//ID: j,
Title: "title",
Desc: "description",
Content: "content",
Tags: []models.Tag{
tags,
},
}
DB.Create(&articles)
}
查
func querym(){
var articles []models.Article2
DB.Preload("Articles").Find(&articles, 1)
DB.Preload("Tags").Find(&articles, 1)
fmt.Println(articles)
}
func querym2() {
var articles models.Article2
DB.First(&articles, 1)
DB.Model(&articles).Association("Tags").Find(&articles.Tags)
fmt.Println(articles)
}
更新
func updatem(){
var articles models.Article2
DB.Preload("Tags").First(&articles, 1)
DB.Model(&articles.Tags).Where("name = ?", "golang").Update("name", "gob")
}
删
func delm() {
var articles models.Article2
DB.Preload("Tags").First(&articles, 1)
DB.Where("name=?", "gob").Delete(&articles.Tags)
}