Gorm

2023-10-16 08:16:00 浏览数 (2)

连接数据库

Mysql

代码语言:javascript复制
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

表操作

自动迁移

自动迁移仅仅会创建表,缺少列和索引,并且不会改变现有列的类型或删除未使用的列以保护数据。

代码语言:javascript复制
db.AutoMigrate(&User{})
db.AutoMigrate(&User{}, &Product{}, &Order{})

判断表是否存在

代码语言:javascript复制
//  检查模型`User`表是否存在
db.HasTable(&User{})
//  检查表`users`是否存在
db.HasTable("users")

创建表

代码语言:javascript复制
db.CreateTable(&User{})

删除表

代码语言:javascript复制
//  删除模型`User`的表
db.DropTable(&User{})
//  删除表`users`
db.DropTable("users")
//  删除模型`User`的表和表`products`
db.DropTableIfExists(&User{}, "products")

列操作

修改列

代码语言:javascript复制
//  修改模型`User`的description列的数据类型为`text`
db.Model(&User{}).DropColumn("description")

删除列

代码语言:javascript复制
db.Model(&User{}).DropColumn("description")

模型

定义模型

模型就是go语言中的结构体。

代码语言:javascript复制
type User struct {
gorm.Model
Age          int
Name         string
}

表名

通过模型创建的表名为该模型名称的复数形式。可以通过重写TableName方法来修改。

代码语言:javascript复制
//  设置User的表名为`profiles`
func (User) TableName() string {
    return "profiles"
}

可以禁用全局复数模式,这样表名会与结构体名相同。

代码语言:javascript复制
db.SingularTable(true)

可以通过重写DefaultTableNameHandler函数更改表名的生成方式。

代码语言:javascript复制
gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string  {
    return "prefix_"   defaultTableName;
}

列名

列名是字段名的蛇形小写。可以通过标签自定义字段对应的列名。

代码语言:javascript复制
// 重设列名
type Animal struct {
    AnimalId    int64     `gorm:"column:beast_id"`         // 设置列名为`beast_id`
    Birthday    time.Time `gorm:"column:day_of_the_beast"` // 设置列名为`day_of_the_beast`
    Age         int64     `gorm:"column:age_of_the_beast"` // 设置列名为`age_of_the_beast`
}

外键

属于关系

默认使用关联属性类型的主键作为关联外键,关联属性类型 主键组成外键名。使用AssociationForeignKey标签自定义关联外键,foreignkey标签自定义外键。 User属于ProfileProfileID为外键。

代码语言:javascript复制
type User struct {
    gorm.Model
    //  指定ProfileID为外键(默认)
    //  指定ID为关联外键(默认)
    Profile   Profile  `gorm:"ForeignKey:ProfileID;AssociationForeignKey:ID"`
    //  外键
    ProfileID int
}
//  它的ID是关联外键
type Profile struct {
    gorm.Model
    Name      string
}

查询示例

代码语言:javascript复制
//  已知user,把它的Profile赋值给profile
db.Model(&user).Related(&profile)
一对一

User包含一个CreditCardUserID为外键。

代码语言:javascript复制
type User struct {
    gorm.Model
    //  指定UserID为外键(默认)
    //  指定ID为关联外键(默认)
    CreditCard   CreditCard  `gorm:"ForeignKey:UserID;AssociationForeignKey:ID"`
}
type CreditCard struct {
    gorm.Model
    //  外键
    UserID   uint
    Number   string
}

查询示例

代码语言:javascript复制
//  已知user,把它的CreditCard 赋值给card
db.Model(&user).Related(&card, "CreditCard")
一对多

User包含多个emailsUserID为外键

代码语言:javascript复制
type User struct {
    gorm.Model
    //  指定UserID为外键(默认)
    //  指定ID为关联外键(默认)
    Emails   []Email  `gorm:"ForeignKey:UserID;AssociationForeignKey:ID"`
}
type Email struct {
    gorm.Model
    Email   string
    //  外键
    UserID  uint
}

查询示例

代码语言:javascript复制
//  已知user,把它的Email赋值给emails
db.Model(&user).Related(&emails)
多对多

User包含并属于多个languages,使用user_languages表连接,默认使用两个表的ID作为外键。

代码语言:javascript复制
type User struct {
    gorm.Model
    Languages         []Language `gorm:"many2many:user_languages;"`
}
type Language struct {
    gorm.Model
    Name string
}

查询示例

代码语言:javascript复制
//  已知user,把它的Language赋值给language
db.Model(&user).Related(&languages, "Languages")
关联模式

从关联字段中查询

代码语言:javascript复制
//  将user关联的Languages赋值给languages
db.Model(&user).Association("Languages").Find(&languages)

添加新的many2many, has_many关联

代码语言:javascript复制
//  向user关联的Languages添加Language实例
db.Model(&user).Association("Languages").Append([]Language{languageZH, languageEN})
db.Model(&user).Association("Languages").Append(Language{Name: "DE"})

删除源和传递的参数之间的关系,不会删除这些参数

代码语言:javascript复制
db.Model(&user).Association("Languages").Delete([]Language{languageZH, languageEN})
db.Model(&user).Association("Languages").Delete(languageZH, languageEN)

使用新的关联替换当前关联

代码语言:javascript复制
db.Model(&user).Association("Languages").Replace([]Language{languageZH, languageEN})
db.Model(&user).Association("Languages").Replace(Language{Name: "DE"}, languageEN)

返回当前关联的计数

代码语言:javascript复制
db.Model(&user).Association("Languages").Count()

删除源和当前关联之间的关系,不会删除这些关联

代码语言:javascript复制
db.Model(&user).Association("Languages").Clear()

数据读写

创建

代码语言:javascript复制
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
db.Create(&user)

查询

代码语言:javascript复制
var user User
var users []User

// 获取第一条记录,按主键排序
db.First(&user)

// 获取最后一条记录,按主键排序
db.Last(&user)

// 获取所有记录
db.Find(&users)

// 使用主键获取记录
db.First(&user, 10)

Where查询(SQL)

代码语言:javascript复制
//  简单查询
db.Where("name = ?", "lihua").First(&user)
//  IN查询
db.Where("name in (?)", []string{"lihua", "lihuahua"}).Find(&users)
//  LIKE查询
db.Where("name LIKE ?", "%li%").Find(&users)
//  AND查询
db.Where("name = ? AND age >= ?", "lihua", "20").Find(&users)
//  按日期查询
db.Where("updated_at > ?", lastWeek).Find(&users)
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)

Where查询(Struct)

代码语言:javascript复制
db.Where(&User{Name: "lihua", Age: 20}).First(&user)

Where查询(Map)

代码语言:javascript复制
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)

Where查询(Slice)

代码语言:javascript复制
//  按主键查询
db.Where([]int64{20, 21, 22}).Find(&users)

Not查询

代码语言:javascript复制
db.Not("name", "lihua").First(&user)

Or查询

代码语言:javascript复制
db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)

查询链

代码语言:javascript复制
db.Where("name <> ?","lihua").Where("age >= ? and role <> ?",20,"admin").Find(&users)

查询或初始化

代码语言:javascript复制
//  存在则赋值给user,否则初始化后再赋值给user
db.FirstOrInit(&user, User{Name: "lihua"})
//  不存在时初始化,并指定参数
db.Attrs(User{Age: 20}).FirstOrInit(&user, User{Name: "lihua"})
//  无论是否存在,都将参数分配到结果
db.Assign(User{Age: 20}).FirstOrInit(&user, User{Name: "lihua"})

查询或创建

代码语言:javascript复制
//  存在则赋值给user,否则创建后再赋值给user
db.FirstOrCreate(&user, User{Name: "lihua"})
//  不存在时创建,并指定参数
db.Attrs(User{Age: 20}).FirstOrCreate(&user, User{Name: "lihua"})
//  无论是否存在,都将参数分配到结果并保存到数据库
db.Assign(User{Age: 20}).FirstOrCreate(&user, User{Name: "lihua"})

Select查询

代码语言:javascript复制
db.Select("name, age").Find(&users)
db.Select([]string{"name", "age"}).Find(&users)
db.Table("users").Select("COALESCE(age,?)", 42).Rows()

Order排序

代码语言:javascript复制
db.Order("age desc, name").Find(&users)
db.Order("age desc").Order("name").Find(&users)
//  重新排序
db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)

Limit指定数量

代码语言:javascript复制
db.Limit(3).Find(&users)
//  取消Limit
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)

Offset跳过记录

代码语言:javascript复制
//  跳过前三个
db.Offset(3).Find(&users)
//  取消跳过
db.Offset(10).Find(&users1).Offset(-1).Find(&users2)

获取记录数

代码语言:javascript复制
db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count)

更新

更新全部字段

代码语言:javascript复制
db.First(&user)
user.Name = "lihuahua"
user.Age = 100
db.Save(&user)

更新指定字段

代码语言:javascript复制
db.Model(&user).Update("name", "hello")
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
//  不会更新值为"",0,false的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18})

指定字段更新,其它忽略

代码语言:javascript复制
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})

指定字段忽略,其它更新

代码语言:javascript复制
db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})

删除

代码语言:javascript复制
// 删除存在的记录
db.Delete(&email)
//  添加额外SQL选项
db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)

批量删除

代码语言:javascript复制
db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
db.Delete(Email{}, "email LIKE ?", "%jinzhu%")

软删除 如果模型有DeletedAt字段,它将自动获得软删除功能! 那么在调用Delete时不会从数据库中永久删除,而是只将字段DeletedAt的值设置为当前时间。

代码语言:javascript复制
//  查找软删除的记录
db.Unscoped().Where("age = 20").Find(&users)
//  永久删除
db.Unscoped().Delete(&user)

0 人点赞