官方文档地址:官方文档,点击跳转

安装: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)
}
分类: go

浙公网安备33011302000604

辽ICP备20003309号