天天看點

gorm使用總結

              時間也會有差錯,也會出故障,它也能被撕成碎片,在一間屋子裡留下一塊永恒的碎屑。

                                                                                                         ——馬爾克斯

目錄

gorm操作的db執行個體

初始化表

普通查詢

使用原生SQL

建立操作

修改操作

删除操作

校驗是否存在

操作時忽略某屬性

gorm結構體Tag

自定義列名稱

使用過程中的一些坑

gorm操作的db執行個體

var db *gorm.DB           

初始化表

  1. //待建立的表對應的結構體
  2. var tables = [] interface{}{
  3. &model.Customer{},
  4. &model.Order{},
  5. &model.OrderItem{},
  6. }
  7. var gdb *gorm.DB
  8. func Connection() *gorm.DB {
  9. return gdb
  10. }
  11. var conn = config.Connection()
  12. func InitTable() {
  13. err := CheckTable()
  14. if err != nil {
  15. log.Fatal( "check table err: ", err.Error())
  16. }
  17. log.Println( "check table completed!")
  18. }
  19. func CheckTable() error {
  20. var err error
  21. for _, table := range tables {
  22. flag := conn.HasTable(table)
  23. if !flag {
  24. err = conn.CreateTable(table).Error
  25. if err != nil {
  26. log.Fatal( "create table err: ", err.Error())
  27. break
  28. }
  29. log.Printf( "create table %v success.", table)
  30. continue
  31. }
  32. }
  33. return err
  34. }

普通查詢

  1. func GetGroupByIDInternal(id string) (group model.MsGroup, err error) (error){
  2. db := config.Connection()
  3. return db.Where( "id = ?", id).Find(&group).Error
  4. }

說明:

1,model.MsGroup 是與資料庫表對應的結構體,以上代碼查詢的就是ms_group表中的資料,

2,條件是以id查詢,

3,一般在查詢的最後使用.Error()來傳回錯誤,查到的所有資料會存到Find方法的參數group這個對象中。

4,有幾個參數就有幾個?

使用原生SQL

  1. //查詢
  2. func ListCatalogAppByProjectIdInternal(projectID string) (gc []model.MsGroupCatalogApp, err error) {
  3. err = config.Connection().Raw( "SELECT * FROM ms_group_catalog_app WHERE deleted_at IS NULL " +
  4. "AND parent_group_id IN (SELECT id FROM ms_group WHERE deleted_at IS NULL AND project_id = ?);", projectID).Find(&gc).Error
  5. return gc, err
  6. }
  7. //其他增删改操作
  8. db.Exec( "UPDATE orders SET shipped_at=? WHERE id IN (?)", time.Now, [] int64{ , , })

說明:

1,以上代碼查詢的是ms_group_catalog_app這個表中的資料,且按自定義需求使用自己寫的SQL,

2,除過使用db.Raw("SQL語句").Find(&對象) 能執行查詢SQL,也可使用

db.Raw("sql語句",變量).Scan(&存放的結構體對象)           

來執行查詢。

建立操作

  1. func CreateGroupCatalogAppInternal(data model.MsGroupCatalogApp) error {
  2. return config.Connection().Create(&data).Error
  3. }

說明:data是你要建立ms_group_catalog_app這個表的待插入記錄

修改操作

  1. //修改所傳的
  2. func updateReceiver(receiver *model.Receiver)error{
  3. return config.Connection().Model(receiver).Where( "id = ?",receiver.Id).Update(receiver).Error
  4. }
  5. //隻修改表中某1列值,如隻修改allow_create的值
  6. func UpdateClusterConfigInternal(conf model.ClusterConfig, tx *gorm.DB) error {
  7. if tx != nil {
  8. return tx.Model(&conf).Where( "cluster_id = ?", conf.ClusterID).Update( "allow_create", conf.AllowCreate).Error
  9. }
  10. return config.Connection().Model(&conf).Where( "cluster_id = ?", conf.ClusterID).Update( "allow_create", conf.AllowCreate).Error
  11. }
  12. //UPDATE cluster_config SET allow_create=conf.AllowCreate, updated_at='2019-7-26 15:34:10' WHERE cluster_id = conf.ID
  13. //修改多個值
  14. func UpdateNormsInternal(norm model.ContainerNorms, tx *gorm.DB) error {
  15. if tx != nil {
  16. return tx.Model(&norm).Where( "id = ?", norm.ID).
  17. Omit( "is_default", "created_at").
  18. Updates( map[ string] interface{}{ "cpu": norm.Cpu, "memory": norm.Memory}).Error
  19. }
  20. return config.Connection().Model(&norm).Where( "id = ?", norm.ID).
  21. Omit( "is_default", "created_at").
  22. Updates( map[ string] interface{}{ "cpu": norm.Cpu, "memory": norm.Memory}).Error
  23. }
  24. //UPDATE container_norms SET memory= norm.Memory,cpu= norm.Cpu, updated_at='2019-7-26 15:34:10' WHERE id = norm.ID

說明:使用Save()方法也能達到目的,但Save()操作的是所有列,慎用。

删除操作

  1. func delReceiver(id string)error{
  2. return config.Connection().Where( "id = ?",id).Delete(&model.Receiver{}).Error
  3. }

校驗是否存在

  1. func CheckReceiverExistByName(Name string)bool{
  2. return config.Connection().Where( "name = ?",Name).Find(&model.Receiver{}).RecordNotFound()
  3. }

在查詢最後使用.RecordNotFound()可直接得知該條記錄是否存在,傳回true則表示沒有這條記錄,傳回false則表明該條資料已存在。

操作時忽略某屬性

  1. func UpdateGroupInternal(group model.MsGroup, tx *gorm.DB) error {
  2. return config.Connection().Model(&group).Where( "id = ?", group.ID).Omit( "name", "created_at", "project_id").Save(&group).Error
  3. }

使用Omit方法,以上代碼是修改操作,修改時将不會修改name,created_at, project_id這三項屬性。

gorm結構體Tag

  1. type Model struct {
  2. ID string `gorm:"primary_key"`
  3. CreatedAt int64
  4. UpdatedAt *time.Time `json:"UpdatedAt,omitempty"`
  5. DeletedAt *time.Time `sql:"index" json:"-"`
  6. }
  7. type MsGroup struct {
  8. Model
  9. Name string `json:"name" gorm:"not null"`
  10. ProjectID string `json:"projectId" gorm:"not null"`
  11. Description string `json:"description"`
  12. Workloads []Workload `json:"workloads" gorm:"-"`
  13. CatalogApps []CatalogApp `json:"catalogApps" gorm:"-"`
  14. }

使用``來寫tag,gorm的tag以gorm開頭,如果屬性是主鍵,标注gorm:"primary_key" ;如果使用了gorm:"-"則表示有關于gorm的操作時忽略這個字段,比如建表時。

常用Tag如下表:

tag名稱 含義
gorm:"primary_key" 主鍵
gorm:"not null" 該屬性不能為空
gorm:"AUTO_INCREMENT" 該屬性自增
gorm:"size:255" 對應的表中長度大小
gorm:"-" 忽略該屬性
gorm:"not null;unique" 設定字段非空且唯一  
gorm:"type:text" 表的該列類型為text

自定義列名稱

預設情況下(不加指定tag時),建表後的列名如下:

  1. type User struct {
  2. ID uint // 列名為 `id`
  3. Name string // 列名為 `name`
  4. Birthday time.Time // 列名為 `birthday`
  5. CreatedAt time.Time // 列名為 `created_at`
  6. }

如果需要自定義列名:

  1. type Animal struct {
  2. AnimalId int64 `gorm:"column:beast_id"` // 設定列名為`beast_id`
  3. Birthday time.Time `gorm:"column:day_of_the_beast"` // 設定列名為`day_of_the_beast`
  4. Age int64 `gorm:"column:age_of_the_beast"` // 設定列名為`age_of_the_beast`
  5. }

即,使用`gorm:"column:name"`

使用過程中的一些坑

1,.Count()函數在特定情況下傳回的記錄數量不是正确的值

解決辦法:調整語句,查詢多次,分别查詢

2,deleted_at是Model結課體的既定字段,删除記錄時表的該條記錄不會實際删除,而是deleted_at置為非空(删除操作時的時間),此時如果你的表結構設計的有些纰漏,那麼功能就會有bug,如ID字段使用未來可能繼續出現的值時。

解決辦法:重新調整列功能及值,增加列

3,當對含有布爾值的結構體進行修改操作時,且修改到了這一列,那麼此時使用.Update(&結構體變量)是不生效的,不生效展現為修改為true時能正常修改,修改為false時資料庫中值不變。那麼這種情況怎麼解決?看上面列舉的修改操作的幾種情況就可以了。

              時間也會有差錯,也會出故障,它也能被撕成碎片,在一間屋子裡留下一塊永恒的碎屑。

                                                                                                         ——馬爾克斯

目錄

gorm操作的db執行個體

初始化表

普通查詢

使用原生SQL

建立操作

修改操作

删除操作

校驗是否存在

操作時忽略某屬性

gorm結構體Tag

自定義列名稱

使用過程中的一些坑

gorm操作的db執行個體

var db *gorm.DB           

初始化表

  1. //待建立的表對應的結構體
  2. var tables = [] interface{}{
  3. &model.Customer{},
  4. &model.Order{},
  5. &model.OrderItem{},
  6. }
  7. var gdb *gorm.DB
  8. func Connection() *gorm.DB {
  9. return gdb
  10. }
  11. var conn = config.Connection()
  12. func InitTable() {
  13. err := CheckTable()
  14. if err != nil {
  15. log.Fatal( "check table err: ", err.Error())
  16. }
  17. log.Println( "check table completed!")
  18. }
  19. func CheckTable() error {
  20. var err error
  21. for _, table := range tables {
  22. flag := conn.HasTable(table)
  23. if !flag {
  24. err = conn.CreateTable(table).Error
  25. if err != nil {
  26. log.Fatal( "create table err: ", err.Error())
  27. break
  28. }
  29. log.Printf( "create table %v success.", table)
  30. continue
  31. }
  32. }
  33. return err
  34. }

普通查詢

  1. func GetGroupByIDInternal(id string) (group model.MsGroup, err error) (error){
  2. db := config.Connection()
  3. return db.Where( "id = ?", id).Find(&group).Error
  4. }

說明:

1,model.MsGroup 是與資料庫表對應的結構體,以上代碼查詢的就是ms_group表中的資料,

2,條件是以id查詢,

3,一般在查詢的最後使用.Error()來傳回錯誤,查到的所有資料會存到Find方法的參數group這個對象中。

4,有幾個參數就有幾個?

使用原生SQL

  1. //查詢
  2. func ListCatalogAppByProjectIdInternal(projectID string) (gc []model.MsGroupCatalogApp, err error) {
  3. err = config.Connection().Raw( "SELECT * FROM ms_group_catalog_app WHERE deleted_at IS NULL " +
  4. "AND parent_group_id IN (SELECT id FROM ms_group WHERE deleted_at IS NULL AND project_id = ?);", projectID).Find(&gc).Error
  5. return gc, err
  6. }
  7. //其他增删改操作
  8. db.Exec( "UPDATE orders SET shipped_at=? WHERE id IN (?)", time.Now, [] int64{ , , })

說明:

1,以上代碼查詢的是ms_group_catalog_app這個表中的資料,且按自定義需求使用自己寫的SQL,

2,除過使用db.Raw("SQL語句").Find(&對象) 能執行查詢SQL,也可使用

db.Raw("sql語句",變量).Scan(&存放的結構體對象)           

來執行查詢。

建立操作

  1. func CreateGroupCatalogAppInternal(data model.MsGroupCatalogApp) error {
  2. return config.Connection().Create(&data).Error
  3. }

說明:data是你要建立ms_group_catalog_app這個表的待插入記錄

修改操作

  1. //修改所傳的
  2. func updateReceiver(receiver *model.Receiver)error{
  3. return config.Connection().Model(receiver).Where( "id = ?",receiver.Id).Update(receiver).Error
  4. }
  5. //隻修改表中某1列值,如隻修改allow_create的值
  6. func UpdateClusterConfigInternal(conf model.ClusterConfig, tx *gorm.DB) error {
  7. if tx != nil {
  8. return tx.Model(&conf).Where( "cluster_id = ?", conf.ClusterID).Update( "allow_create", conf.AllowCreate).Error
  9. }
  10. return config.Connection().Model(&conf).Where( "cluster_id = ?", conf.ClusterID).Update( "allow_create", conf.AllowCreate).Error
  11. }
  12. //UPDATE cluster_config SET allow_create=conf.AllowCreate, updated_at='2019-7-26 15:34:10' WHERE cluster_id = conf.ID
  13. //修改多個值
  14. func UpdateNormsInternal(norm model.ContainerNorms, tx *gorm.DB) error {
  15. if tx != nil {
  16. return tx.Model(&norm).Where( "id = ?", norm.ID).
  17. Omit( "is_default", "created_at").
  18. Updates( map[ string] interface{}{ "cpu": norm.Cpu, "memory": norm.Memory}).Error
  19. }
  20. return config.Connection().Model(&norm).Where( "id = ?", norm.ID).
  21. Omit( "is_default", "created_at").
  22. Updates( map[ string] interface{}{ "cpu": norm.Cpu, "memory": norm.Memory}).Error
  23. }
  24. //UPDATE container_norms SET memory= norm.Memory,cpu= norm.Cpu, updated_at='2019-7-26 15:34:10' WHERE id = norm.ID

說明:使用Save()方法也能達到目的,但Save()操作的是所有列,慎用。

删除操作

  1. func delReceiver(id string)error{
  2. return config.Connection().Where( "id = ?",id).Delete(&model.Receiver{}).Error
  3. }

校驗是否存在

  1. func CheckReceiverExistByName(Name string)bool{
  2. return config.Connection().Where( "name = ?",Name).Find(&model.Receiver{}).RecordNotFound()
  3. }

在查詢最後使用.RecordNotFound()可直接得知該條記錄是否存在,傳回true則表示沒有這條記錄,傳回false則表明該條資料已存在。

操作時忽略某屬性

  1. func UpdateGroupInternal(group model.MsGroup, tx *gorm.DB) error {
  2. return config.Connection().Model(&group).Where( "id = ?", group.ID).Omit( "name", "created_at", "project_id").Save(&group).Error
  3. }

使用Omit方法,以上代碼是修改操作,修改時将不會修改name,created_at, project_id這三項屬性。

gorm結構體Tag

  1. type Model struct {
  2. ID string `gorm:"primary_key"`
  3. CreatedAt int64
  4. UpdatedAt *time.Time `json:"UpdatedAt,omitempty"`
  5. DeletedAt *time.Time `sql:"index" json:"-"`
  6. }
  7. type MsGroup struct {
  8. Model
  9. Name string `json:"name" gorm:"not null"`
  10. ProjectID string `json:"projectId" gorm:"not null"`
  11. Description string `json:"description"`
  12. Workloads []Workload `json:"workloads" gorm:"-"`
  13. CatalogApps []CatalogApp `json:"catalogApps" gorm:"-"`
  14. }

使用``來寫tag,gorm的tag以gorm開頭,如果屬性是主鍵,标注gorm:"primary_key" ;如果使用了gorm:"-"則表示有關于gorm的操作時忽略這個字段,比如建表時。

常用Tag如下表:

tag名稱 含義
gorm:"primary_key" 主鍵
gorm:"not null" 該屬性不能為空
gorm:"AUTO_INCREMENT" 該屬性自增
gorm:"size:255" 對應的表中長度大小
gorm:"-" 忽略該屬性
gorm:"not null;unique" 設定字段非空且唯一  
gorm:"type:text" 表的該列類型為text

自定義列名稱

預設情況下(不加指定tag時),建表後的列名如下:

  1. type User struct {
  2. ID uint // 列名為 `id`
  3. Name string // 列名為 `name`
  4. Birthday time.Time // 列名為 `birthday`
  5. CreatedAt time.Time // 列名為 `created_at`
  6. }

如果需要自定義列名:

  1. type Animal struct {
  2. AnimalId int64 `gorm:"column:beast_id"` // 設定列名為`beast_id`
  3. Birthday time.Time `gorm:"column:day_of_the_beast"` // 設定列名為`day_of_the_beast`
  4. Age int64 `gorm:"column:age_of_the_beast"` // 設定列名為`age_of_the_beast`
  5. }

即,使用`gorm:"column:name"`

使用過程中的一些坑

1,.Count()函數在特定情況下傳回的記錄數量不是正确的值

解決辦法:調整語句,查詢多次,分别查詢

2,deleted_at是Model結課體的既定字段,删除記錄時表的該條記錄不會實際删除,而是deleted_at置為非空(删除操作時的時間),此時如果你的表結構設計的有些纰漏,那麼功能就會有bug,如ID字段使用未來可能繼續出現的值時。

解決辦法:重新調整列功能及值,增加列

3,當對含有布爾值的結構體進行修改操作時,且修改到了這一列,那麼此時使用.Update(&結構體變量)是不生效的,不生效展現為修改為true時能正常修改,修改為false時資料庫中值不變。那麼這種情況怎麼解決?看上面列舉的修改操作的幾種情況就可以了。