开发者

golang Gorm框架讲解

目录
  • 1.gorm介绍
    • 1.1介绍
    • 1.2安装
  • 2.使用
    • 2.1创建表
    • 2.2.添加数据
    • 2.3.查询数据
    • 2.4更新数据
    • 2.5删除数据
    • 2.6执行原生sql
  • 3.一对一
    • 3.1创建表
    • 3.2多态关联
    • 3.3外键约束
  • 4.一对多
    • 5.多对多
      • 6.获取多表数据

        1.gorm介绍

        1.1介绍

        全功能 ORM
        关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)
        Create,Save,Update,Delete,Find 中钩子方法
        支持 Preload、Joins 的预加载
        事务,嵌套事务,Save Point,Rollback To Saved Point
        Context,预编译模式,DryRun 模式
        批量插入,FindInBATches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD
        SQL 构建器,Upsert,数据库锁,Optimizer/Index/Comment Hint,命名参数,子查询
        复合主键,索引,约束
        Auto Migration
        自定义 Logger
        灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…
        每个特性都经过了测试的重重考验
        开发者友好

        1.2安装

        go get -u gorm.io/gorm
        go get -u gorm.io/driver/SQLite

        2.使用

        2.1创建表

        package main
        
        import (
        	"fmt"
        
        	"gorm.io/driver/mysql"
        	"gorm.io/gorm"
        )
        
        //模型结构
        type Student struct {
        	Id   int
        	Name string
        	Age  int
        }
        
        type User struct {
        	gorm.Model
        	Name string `gorm:"type:varchar(20);not null"`
        	Telephone string `gorm:"varchar(110;not null;unique"`
        	Password string `gorm:"size:255;not null"`
        }
        func main() {
        	//使用dsn连接到数据库,grom自带的数据库池
        	//账号:密码@连接方式(ip地址:端口号)/数据库?语言方式,时区(未设置时区的话采用8小时制度)
        	dsn := "root:mysql@tcp(127.0.0.1:3306)/gotest?charset=utf8mb4&parseTime=True&loc=Local"
        	conn, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
        	if err != nil {
        		fmt.Println(err)
        	}
        	conn.AutoMigrate(&Student{}) //创建表?判断是否表结构存在
        }
        
        //多表创建
        db.AutoMigrate(&Company{}, &Worker{})
        

        2.2.添加数据

        stu := &Student{
        		Id:   3,
        		Name: "li333",
        		Age:  30,
        	}
        	res := conn.Create(stu) //向数据库中插入数据  ,它的返回值只有一个类型,没有error类型
        	//注:如果上面写成stu := Student{...},则这里写成Create(&stu)
        
        	if res.Error != nil { //判断是否插入数据出错
        		fmt.Println(res.Error)
        	}

        2.3.查询数据

        var student Student
        	//查询First查询一条
        	conn.First(&student)
        	fmt.Println(student)
        	fmt.Println(student.Id)
        	//条件查询
        	res := conn.First(&student, "name=? and id=?", "yang", 1)
        	fmt.Println(res)
         //查询所有 Find
        	var stu []Student
        	conn.Table("students").Find(&stu)
        	for _, v := range stu {
        		fmt.Println(v.Name)
        	}
        
         // IN
        	var students []Student
        	conn.Table("students").Where("name IN ?", []string{"abc", "bili"}).Find(&students)
        	fmt.Println(students)
        
        	// LIKE
        	db.Where("name LIKE ?", "%jin%").Find(&users)
        
        	// AND
        	db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
        
        	// Time
        	db.Where("updated_at > ?", time.Date(2022,05,20,0,0,0,0,&time.Location{})).Find(&users)
        
        	// BETWEEN
        	db.Where("created_at BETWEEN ? AND ?", time.Date(2022,05,20,0,0,0,0,&time.Location{}), time.Now()).Find(&users)
        

        2.4更新数据

          //更新数据
        	conn.Table("students").Where("id=?", 1).Update("name", "ttt")
        	conn.Table("students").Where("idTCOtzTn=?", 2).Updates(&Student{Name: "bili", Age: 10})
        	//按主键更新,传入结构体对象,根据对应主键更新相应内容
          dbConn.Table("user").Save(&user1)

        2.5删除数据

        conn.Table("students").Where("id=?", 1).Delete(&Student{})

        2.6执行原生sql

        conn.Raw("select * from students where id=?", 3).Scan(&student)
        fmt.Println(student)
        
        db.Exec("DROP TABLE users")
        db.Exec("UPDATE orders SET shipped_at=? WHERE id IN ?", time.Now(), []int64{1,2,3})

        3.一对一

        3.1创建表

        package main
        
        import (
        	"fmt"
        
        	"gorm.io/driver/mysql"
        	"gorm.io/gorm"
        )
        
        type User str编程uct {
        	gorm.Model
        	CreditCard CreditCard
        	Name       string
        }
        
        type CreditCard struct {
        	gorm.Model
        	Number string
        	UserID uint
        }
        
        func main() {
        	//使用dsn连接到数据库,grom自带的数据库池
        	//账号:密码@连接方式(ip地址:端口号)/数据库?语言方式,时区(未设置时区的话采用8小时制度)
        	dsn := "root:mysql@tcp(127.0.0.1:3306)/crow?charset=utf8mb4&parseTime=True&loc=Local"
        	conn, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
        	if err != nil {
        		fmt.Println(err)
        	}
        	conn.AutoMigrate(&User{})
        	conn.AutoMigrate(&CreditCard{})
        
        	//创建表?判断是否表结构存在
        	user := &User{
        		Name: "李四",
        	}
        
        	conn.Create(user)
        
        	card := &CreditCard{
        		Number: "123",
        		UserID: 1,
        	}
        	conn.Create(card)
        
        }

        3.2多态关联

        //多态关联
        //GORM 为 has one 和 has many 提供了多态关联支持,它会将拥有者实体的表名、主键值都保存到多态类型的字段中。
        
        type Cat struct {
          ID    int
          Name  string
          Toy   Toy `gorm:"polymorphic:Owner;"`
        }
        
        type Dog struct {
          ID   int
          Name string
          Toy  Toy `gorm:"polymorphic:Owner;"`
        }
        
        type Toy struct {
          ID        int
          Name      string
          OwnerID   int
          OwnerType string
        }
        
        db.Create(&Dog{Name: "dog1", Toy: Toy{Name: "toy1"}})
        // INSERT INTO `dogs` (`name`) VALUES ("dog1")
        // INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","dogs")

        3.3外键约束

        你可以通过为标签 constraint 配置 OnUpdateOnDelete 实现外键约束,在使用 GORM 进行迁移时它会被创建,例如:

        type User struct {
          gorm.Model
          Name      string
          CompanyID int
          Company   androidCompany `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
        }
        
        type Company struct {
          ID   int
          Name string
        }

        4.一对多

        Has Many

        has many 与另一个模型建立了一对多的连接。 不同于 has one,拥有者可以有零或多个关联模型。

        例如,您的应用包含 user 和 credit card 模型,且每个 user 可以有多张 credit card。

        // User 有多张 CreditCard,UserID 是外键
        type User struct {
          gorm.Model
          CreditCards []CreditCard
        }
        
        type CreditCard struct {
          gorm.Model
          Number string
          UserID uint
        }
        package main
        
        import (
        	"fmt"
        
        	"gorm.io/driver/mysql"
        	"gorm.io/gorm"
        )
        
        开发者_Python
        type User struct {
        	gorm.Model
        	MemberNumber string       `gorm:"varchar(110;not null;unique"`
        	CreditCards  []CreditCard `gorm:"foreignKey:UserNumber;references:MemberNumber"`
        	Name         string
        }
        
        type CreditCard struct {
        	gorm.Model
        	Number     string
        	UserNumber string `gorm:"varchar(110;not null;unique"`
        }
        
        func main() {
        	//使用dsn连接到数据库,grom自带的数据库池
        	//账号:密码@连接方式(ip地址:端口号)/数据库?语言方式,时区(未设置时区的话采用8小时制度)
        	dsn := "root:mysql@tcp(127.0.0.1:3306)/crow?charset=utf8mb4&parseTime=True&loc=Local"
        	cjavascriptonn, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
        	if err != nil {
        		fmt.Println(err)
        	}
        	conn.AutoMigrate(&User{}, &CreditCard{})
        	user := User{
        		Name:         "ttt3",
        		MemberNumber: "1003",
        	}
        	conn.Create(&user)
        	card := CreditCard{
        		Number:     "111",
        		UserNumber: user.MemberNumber,
        	}
        	conn.Create(&card)
        
        }
        
        
        

        5.多对多

        Many To Many

        Many to Many 会在两个 model 中添加一张连接表。

        例如,您的应用包含了 user 和 language,且一个 user 可以说多种 language,多个 user 也可以说一种 language。

        // User 拥有并属于多种 language,`user_languages` 是连接表
        type User struct {
          gorm.Model
          Languages []Language `gorm:"many2many:user_languages;"`
        }
        
        type Language struct {
          gorm.Model
          Name string
        }

        当使用 GORM 的 AutoMigrateUser 创建表时,GORM 会自动创建连接表

        反向引用

        // User 拥有并属于多种 language,`user_languages` 是连接表
        type User struct {
          gorm.Model
          Languages []*Language `gorm:"many2many:user_languages;"`
        }
        
        type Language struct {
          gorm.Model
          Name string
          Users []*User `gorm:"many2many:user_languages;"`
        }

        重写外键

        对于 many2many 关系,连接表会同时拥有两个模型的外键,例如:

        type User struct {
          gorm.Model
          Languages []Language `gorm:"many2many:user_languages;"`
        }
        
        type Language struct {
          gorm.Model
          Name string
        }
        
        // Join Table: user_languages
        //   foreign key: user_id, reference: users.id
        //   foreign key: language_id, reference: languages.id

        若要重写它们,可以使用标签 foreignKeyreferencejoinforeignKeyjoinReferences。当然,您不需要使用全部的标签,你可以仅使用其中的一个重写部分的外键、引用。

        type User struct {
            gorm.Model
            Profiles []Profile `gorm:"many2many:user_profiles;foreignKey:Refer;joinForeignKey:UserReferID;References:UserRefer;JoinReferences:UserRefer"`
            Refer    uint
        }
        
        type Profile struct {
            gorm.Model
            Name      string
            UserRefer uint
        }
        
        // 会创建连接表:user_profiles
        //   foreign key: user_refer_id, reference: users.refer
        //   foreign key: profile_refer, reference: profiles.user_refer

        自引用 Many2Many

        自引用 many2many 关系

        type User struct {
          gorm.Model
            Friends []*User `gorm:"many2many:user_friends"`
        }
        
        // 会创建连接表:user_friends
        //   foreign key: user_id, reference: users.id
        //   foreign key: friend_id, reference: users.id

        6.获取多表数据

        预加载

        GORM 允许在 Preload 的其它 SQL 中直接加载关系,例如:

        type User struct {
          gorm.Model
          Username string
          Orders   []Order
        }
        
        type Order struct {
          gorm.Model
          UserID uint
          Price  float64
        }
        
        // 查找 user 时预加载相关 Order
        db.Preload("Orders").Find(&users)
        // SELECT * FROM users;
        // SELECT * FROM orders WHERE user_id IN (1,2,3,4);
        
        db.Preload("Orders").Preload("Profile").Preload("Role").Find(&users)
        // SELECT * FROM users;
        // SELECT * FROM orders WHERE user_id IN (1,2,3,4); // has many
        // SELECT * FROM profiles WHERE user_id IN (1,2,3,4); // has one
        // SELECT * FROM roles WHERE id IN (4,5,6); // belongs to

        Joins 预加载

        Preload 在一个单独查询中加载关联数据。而 Join Preload 会使用 inner join 加载关联数据,例如:

        db.Joins("Company").Joins("Manager").Joins("Account").First(&user, 1)
        db.Joins("Company").Joins("Manager").Joins("Account").First(&user, "users.name = ?", "jinzhu")
        db.Joins("Company").Joins("Manager").Joins("Account").Find(&users, "users.id IN ?", []int{1,2,3,4,5})

        注意 Join Preload 适用于一对一的关系,例如: has one, belongs to

        预加载全部

        与创建、更新时使用 Select 类似,clause.Associations 也可以和 Preload 一起使用,它可以用来 预加载 全部关联,例如:

        type User struct {
          gorm.Model
          Name       string
          CompanyID  uint
          Company    Company
          Role       Role
        }
        
        db.Preload(clause.Associations).Find(&users)

        带条件的预加载

        GORM 允许带条件的 Preload 关联,类似于内联条件

        // 带条件的预加载 Order
        db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
        // SELECT * FROM users;
        // SELECT * FROM orders WHERE user_id IN (1,2,3,4) AND state NOT IN ('cancelled');
        
        db.Where("state = ?", "active").Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
        // SELECT * FROM users WHERE state = 'active';
        // SELECT * FROM orders WHERE user_id IN (1,2) AND state NOT IN ('cancelled');

        自定义预加载 SQL

        您可以通过 func(db *gorm.DB) *gorm.DB 实现自定义预加载 SQL,例如:

        db.Preload("Orders", func(db *gorm.DB) *gorm.DB {
          return db.Order("orders.amount DESC")
        }).Find(&users)
        // SELECT * FROM users;
        // SELECT * FROM orders WHERE user_id IN (1,2,3,4) order by orders.amount DESC;

        嵌套预加载

        GORM 支持嵌套预加载,例如:

        db.Preload("Orders.OrderItems.Product").Preload("CreditCard").Find(&users)php
        
        // 自定义预加载 `Orders` 的条件
        // 这样,GORM 就不会加载不匹配的 order 记录
        db.Preload("Orders", "state = ?", "paid").Preload("Orders.OrderItems").Find(&users)

        到此这篇关于golang Gorm框架的文章就介绍到这了,更多相关golang Gorm框架内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

        0

        上一篇:

        下一篇:

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        最新开发

        开发排行榜