还是继续学习GORM文档,不知道这个学习顺序对不对。这篇文章主要说的第二大部分模型。我这个就是做个笔记平日翻看方便,建议大家可以去看原版的文档,这一篇有的精简有的增加。我看着方便,大家就根据自己的需求吧
1.模型定义
先随便来一个user的结构体(我感觉这个java pojo类从差不多)
type User struct {
gorm.Model
Birthday time.Time
Age int
Name string `gorm:"size:255"` //string默认长度为255, 使用这种tag重设。
Num int`gorm:"AUTO_INCREMENT"` //自增
CreditCard CreditCard //One-To-One (拥有一个 - CreditCard表的UserID作外键)
Emails []Email //One-To-Many (拥有多个 - Email表的UserID作外键)
BillingAddress Address //One-To-One (属于 - 本表的BillingAddressID作外键)
BillingAddressID sql.NullInt64
ShippingAddress Address //One-To-One (属于 - 本表的ShippingAddressID作外键)
ShippingAddressID int
IgnoreMe int`gorm:"-"` //忽略这个字段
Languages []Language `gorm:"many2many:user_languages;"` //Many-To-Many , 'user_languages'是连接表
}
type Email struct{
ID int
UserID int `gorm:"index"` //外键 (属于), tag `index`是为该列创建索引 Email string `gorm:"type:varchar(100);unique_index"` //`type`设置sql类型, `unique_index` 为该列设置唯一索引
Subscribed bool
}
type Address struct{
ID int
Address1 string `gorm:"not null;unique"` //设置字段为非空并唯一
Address2 string `gorm:"type:varchar(100);unique"`
Post sql.NullString `gorm:"not null"`
}
type Language struct{
ID int
Name string `gorm:"index:idx_name_code"` //创建索引并命名,如果找到其他相同名称的索引则创建组合索引
Code string `gorm:"index:idx_name_code"` //`unique_index` also works
}
2.约定
(1)gorm.Model 结构体
type Model struct{
ID uint `gorm:"primary_key"` //主键id
CreatedAt time.Time //记录创建时间
UpdatedAt time.Time //记录的修改时间
DeletedAt *time.Time //记录删除时间(如果字段存在)
}
基本模型包含了四个字段:ID,CreatedAt,UpdatedAt,DeletedAt。这是可以直接嵌入使用的,当然也可以增加你需要的字段。例如:
type User struct{
gorm.Model //基本模型
Name string //自己新增加的
}
(2)表名是结构体名称的复数形式
type User struct{} //一个结构体出来它默认表名是`users`(+s)
func (User //实体名) TableName() string { //部份表使用源表名,在实体类中声明
return"profiles" //设置User的表名为`profiles`
}
func (u User) TableName() string{
if u.Role =="admin"{ //获取当前用户的名称
return"admin_users"
}else{
return"users"
}
}
//全局禁用表名复数,如果不禁止会出现y结尾变ies问题
db.SingularTable(true) //如果设置为true,`User`的默认表名为`user`,使用`TableName`设置的表名不受影响
(3)更改默认表名
gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string {
return"prefix_"+ defaultTableName;
}
(4)列名是字段名的蛇形小写(使用小写+"_")
列名均为小写,例如:
ID uint 的列名为 id 。
当然我们也可以重新设置列名,例如:
AnimalId int64 `gorm:"column:beast_id"` //设置列名为`beast_id`
(5)设置主键
通常情况下,字段id默认为主键。当然也可以设置主键例如:
AnimalId int64 `gorm:"primary_key"` //设置AnimalId为主键
3.关联
(1)属于
有两个结构体A和B结构体A内字段是结构体B,则A属于B。例如:
type A struct {
gorm. Modle
Bb B `gorm:"ForeignKey:Bid"` //使用Bid作为外键
//Bb B `gorm:"AssociationForeignKey:Bid"` 使用Bid作为关联外键
Bid int
}
type B struct {
gorm.Model
Name string
}
db.Model(&A).Related(&B) //可以使用Related查找这个关系(一对一)
(2)包含一个
type A truct{ //A中包含一个B
gorm.Model
Refer string
B B //字段名与变量名相同
//B B `gorm:"ForeignKey:AID"` :指定外键
//B B `gorm:"ForeignKey:AID;AssociationForeignKey:Refer"` :指定外键和关联外键
}
type B struct{
gorm.Model
AID uint //外键
Number string
}
var b B //先来一个B
db.Model(&A).Related(&b,"B") //B是A中的字段名并且字段名与变量名相同,也可以这样写:db.Model(&A.Related(&b)
(3)包含多个
type A struct {
gorm.Model
Refer string
B []B //A包含多个B
//B []B `gorm:"ForeignKey:Aid"` 指定外键
//B []B `gorm:"ForeignKey:AID;AssociationForeignKey:Refer"` 指定外键和关联外键
}
type B struct {
gorm.Model
B string
AID uint
}
db.Model(&A).Related(&B) //查询
(4)多对多
// User 包含并属于多个 languages, 使用 `user_languages` 表连接
type A struct {
gorm.Model
ID string
Bs []B `gorm:"many2many:A_Bs;"` //A中包含并属于多个Bs,使用A_Bs
// Bs []B `gorm:"many2many:AB;ForeignKey:ID;AssociationForeignKey:Bid"` 指定外键和关联键
}
type B struct {
gorm.Model
Bid string
Name string `gorm:"primary_key:true"` //指定外键
}
db.Model(&A).Related(&Bs,"Bs")
(5)多种包含
支持多种的包含一个和包含多个的关联;不支持多态属性和多对多显式,并且会抛出错误。
type Cat struct {
Id int
Name string
Toy Toy `gorm:"polymorphic:Owner;"`
}
type Dogs truct {
Id int
Name string
Toy Toy `gorm:"polymorphic:Owner;"`
}
type Toy struct {
Id int
Name string
OwnerId int
OwnerType string
}
(6)关联模式(包含一些帮助方法来处理关系事情)
type User struct {
gorm.Model
Languages []Language
}
type Language struct {
gorm.Model
Name string
}
var user User //先来一个,开始关联模式
db.Model(&user).Association("Languages") //user是源,它需要一个有效的记录(包含主键);Languages是关系中源的字段名,如果条件不匹配,则返回一个错误来检查它:db.Model(&user).Association("Languages").Error
db.Model(&user).Association("Languages").Find(&languages) //Query - 查找所有相关关联
db.Model(&user).Association("Languages").Append([]Language{languageZH, languageEN}) //Append - 添加新的many2many, has_many关联, 会替换掉当前 has_one, belongs_to关联
db.Model(&user).Association("Languages").Delete([]Language{languageZH, languageEN}) //Delete - 删除源和传递的参数之间的关系,不会删除这些参数
db.Model(&user).Association("Languages").Replace([]Language{languageZH, languageEN}) //Replace - 使用新的关联替换当前关联
db.Model(&user).Association("Languages").Count() //Count - 返回当前关联的计数
db.Model(&user).Association("Languages").Clear() //Clear - 删除源和当前关联之间的关系,不会删除这些关联