Gorm
## 连接数据库 ### Mysql ```go 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{}) ``` ## 表操作 ### 自动迁移 自动迁移仅仅会创建表,缺少列和索引,并且不会改变现有列的类型或删除未使用的列以保护数据。 ```go db.AutoMigrate(&User{}) db.AutoMigrate(&User{}, &Product{}, &Order{}) ``` ### 判断表是否存在 ```go // 检查模型`User`表是否存在 db.HasTable(&User{}) // 检查表`users`是否存在 db.HasTable("users") ``` ### 创建表 ```go db.CreateTable(&User{}) ``` ### 删除表 ```go // 删除模型`User`的表 db.DropTable(&User{}) // 删除表`users` db.DropTable("users") // 删除模型`User`的表和表`products` db.DropTableIfExists(&User{}, "products") ``` ## 列操作 ### 修改列 ```go // 修改模型`User`的description列的数据类型为`text` db.Model(&User{}).DropColumn("description") ``` ### 删除列 ```go db.Model(&User{}).DropColumn("description") ``` ## 模型 ### 定义模型 模型就是go语言中的结构体。 ```go type User struct { gorm.Model Age int Name string } ``` ### 表名 通过模型创建的表名为该模型名称的复数形式。可以通过重写`TableName`方法来修改。 ```go // 设置User的表名为`profiles` func (User) TableName() string { return "profiles" } ``` 可以禁用全局复数模式,这样表名会与结构体名相同。 ```go db.SingularTable(true) ``` 可以通过重写`DefaultTableNameHandler`函数更改表名的生成方式。 ```go gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string { return "prefix_" + defaultTableName; } ``` ### 列名 列名是字段名的蛇形小写。可以通过标签自定义字段对应的列名。 ```go // 重设列名 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`为外键。 ```go type User struct { gorm.Model // 指定ProfileID为外键(默认) // 指定ID为关联外键(默认) Profile Profile `gorm:"ForeignKey:ProfileID;AssociationForeignKey:ID"` // 外键 ProfileID int } // 它的ID是关联外键 type Profile struct { gorm.Model Name string } ``` 查询示例 ```go // 已知user,把它的Profile赋值给profile db.Model(&user).Related(&profile) ``` #### 一对一 `User`包含一个`CreditCard`,`UserID`为外键。 ```go type User struct { gorm.Model // 指定UserID为外键(默认) // 指定ID为关联外键(默认) CreditCard CreditCard `gorm:"ForeignKey:UserID;AssociationForeignKey:ID"` } type CreditCard struct { gorm.Model // 外键 UserID uint Number string } ``` 查询示例 ```go // 已知user,把它的CreditCard 赋值给card db.Model(&user).Related(&card, "CreditCard") ``` #### 一对多 `User`包含多个`emails`,`UserID`为外键 ```go type User struct { gorm.Model // 指定UserID为外键(默认) // 指定ID为关联外键(默认) Emails []Email `gorm:"ForeignKey:UserID;AssociationForeignKey:ID"` } type Email struct { gorm.Model Email string // 外键 UserID uint } ``` 查询示例 ```go // 已知user,把它的Email赋值给emails db.Model(&user).Related(&emails) ``` #### 多对多 ```go `User`包含并属于多个`languages`,使用`user_languages`表连接,默认使用两个表的`ID`作为外键。 type User struct { gorm.Model Languages []Language `gorm:"many2many:user_languages;"` } type Language struct { gorm.Model Name string } ``` 查询示例 ```go // 已知user,把它的Language赋值给language db.Model(&user).Related(&languages, "Languages") ``` #### 关联模式 从关联字段中查询 ```go // 将user关联的Languages赋值给languages db.Model(&user).Association("Languages").Find(&languages) ``` 添加新的many2many, has_many关联 ```go // 向user关联的Languages添加Language实例 db.Model(&user).Association("Languages").Append([]Language{languageZH, languageEN}) db.Model(&user).Association("Languages").Append(Language{Name: "DE"}) ``` 删除源和传递的参数之间的关系,不会删除这些参数 ```go db.Model(&user).Association("Languages").Delete([]Language{languageZH, languageEN}) db.Model(&user).Association("Languages").Delete(languageZH, languageEN) ``` 使用新的关联替换当前关联 ```go db.Model(&user).Association("Languages").Replace([]Language{languageZH, languageEN}) db.Model(&user).Association("Languages").Replace(Language{Name: "DE"}, languageEN) ``` 返回当前关联的计数 ```go db.Model(&user).Association("Languages").Count() ``` 删除源和当前关联之间的关系,不会删除这些关联 ```go db.Model(&user).Association("Languages").Clear() ``` ## 数据读写 ### 创建 ```go user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()} db.Create(&user) ``` ### 查询 ```go var user User var users []User // 获取第一条记录,按主键排序 db.First(&user) // 获取最后一条记录,按主键排序 db.Last(&user) // 获取所有记录 db.Find(&users) // 使用主键获取记录 db.First(&user, 10) ``` Where查询(SQL) ```go // 简单查询 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) ```go db.Where(&User{Name: "lihua", Age: 20}).First(&user) ``` Where查询(Map) ```go db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users) ``` Where查询(Slice) ```go // 按主键查询 db.Where([]int64{20, 21, 22}).Find(&users) ``` Not查询 ```go db.Not("name", "lihua").First(&user) ``` Or查询 ```go db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users) ``` 查询链 ```go db.Where("name <> ?","lihua").Where("age >= ? and role <> ?",20,"admin").Find(&users) ``` 查询或初始化 ```go // 存在则赋值给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"}) ``` 查询或创建 ```go // 存在则赋值给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查询 ```go db.Select("name, age").Find(&users) db.Select([]string{"name", "age"}).Find(&users) db.Table("users").Select("COALESCE(age,?)", 42).Rows() ``` Order排序 ```go 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指定数量 ```go db.Limit(3).Find(&users) // 取消Limit db.Limit(10).Find(&users1).Limit(-1).Find(&users2) ``` Offset跳过记录 ```go // 跳过前三个 db.Offset(3).Find(&users) // 取消跳过 db.Offset(10).Find(&users1).Offset(-1).Find(&users2) ``` 获取记录数 ```go db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count) ``` ### 更新 更新全部字段 ```go db.First(&user) user.Name = "lihuahua" user.Age = 100 db.Save(&user) ``` 更新指定字段 ```go 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}) ``` 指定字段更新,其它忽略 ```go db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false}) ``` 指定字段忽略,其它更新 ```go db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false}) ``` ### 删除 ```go // 删除存在的记录 db.Delete(&email) // 添加额外SQL选项 db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email) ``` 批量删除 ```go db.Where("email LIKE ?", "%jinzhu%").Delete(Email{}) db.Delete(Email{}, "email LIKE ?", "%jinzhu%") ``` 软删除 如果模型有DeletedAt字段,它将自动获得软删除功能! 那么在调用Delete时不会从数据库中永久删除,而是只将字段DeletedAt的值设置为当前时间。 ```go // 查找软删除的记录 db.Unscoped().Where("age = 20").Find(&users) // 永久删除 db.Unscoped().Delete(&user) ``` ## 标签 | 标签名 | 说明 | | ------- | ----- | | column | 列名 | | type | 数据类型 | | size | 大小 | | primaryKey | 主键 | | unique | 唯一 | | default | 默认值 | | precision | 精度 | | scale | 列大小 | | not null | 不为空 | | autoIncrement | 自增,不可与primaryKey、type同时使用否则不生效 | | autoIncrementIncrement | 自动步长,控制连续记录之间的间隔 | | embedded | 嵌套字段 | | embeddedPrefix | 嵌套字段前缀 | | autoCreateTime | 创建时追踪当前时间,对于 int 字段,它会追踪秒级时间戳,可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoCreateTime:milli | | autoUpdateTime | 创建/更新时追踪当前时间,对于 int 字段,它会追踪秒级时间戳,可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milli | | index | 根据参数创建索引,多个字段使用相同的名称则创建复合索引 | | uniqueIndex | 创建唯一索引 | | check | 创建检查约束,例如 check:age > 13 | | comment | 迁移时为字段添加注释 | | - | 忽略该字段,- 无读写权限 |
创建时间:2023-10-13
|
最后修改:2023-12-27
|
©允许规范转载
酷酷番茄
首页
文章
友链