连接数据库
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
方法来修改。
// 设置User的表名为`profiles`
func (User) TableName() string {
return "profiles"
}
可以禁用全局复数模式,这样表名会与结构体名相同。
代码语言:javascript复制db.SingularTable(true)
可以通过重写DefaultTableNameHandler
函数更改表名的生成方式。
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
属于Profile
,ProfileID
为外键。
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
包含一个CreditCard
,UserID
为外键。
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
包含多个emails
,UserID
为外键
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
作为外键。
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)