gorm多條數據級聯查詢關聯查詢gorm連接池gorm事務

因爲gorm支持級聯查詢。xorm的jion查詢雖然很棒,但是查出來的不能生成嵌套結構體。而gorm就可以,經過摸索,這種關聯啊,預加載啊,雖然沒搞清楚他們之間的區別,但總算能滿足自己的查詢需要了。
網絡上都是單條記錄的關聯查詢,而我需要對多條記錄進行關聯查詢,目前只知道使用preload

//查詢某個用戶打賞記錄
func GetUserPay(uid int64, limit, offset int) (pays []*Pay, err error) {
	//獲取DB
	db := GetDB()
	// err = db.Where("user_id", uid).Find(&pays).Error
	err = db.Model(&pays).Preload("User").Preload("Article").Where("user_id=?", uid).Limit(limit).Offset(offset).Find(&pays).Error //查詢所有device記錄
	// err = db.Model(&pays).Related(&pays.User, "Users").Error
	return pays, err
	// 多連接及參數
	// db.Joins("JOIN pays ON pays.user_id = users.id", "[email protected]").Joins("JOIN credit_cards ON credit_cards.user_id = users.id").Where("user_id = ?", uid).Find(&pays)
}

還有就是連接池,因爲在beego中用,除了beego的orm外,還用了xorm,這次再加入gorm,就3個了,他們如何連接數據庫也是費了不少心思。說gorm用連接池,每次使用的時候要調用一下?

使用了gorm的事務,作爲小程序讚賞時,用戶賬戶扣款,文章獲得讚賞,用戶賬戶餘額減少。

//添加某個文章某個用戶打賞記錄
func AddUserPay(articleid, uid int64, amount int) error {
	//獲取DB
	db := GetDB()
	// 注意,當你在一個事務中應使用 tx 作爲數據庫句柄
	tx := db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	if err := tx.Error; err != nil {
		return err
	}
	//保證文章id正確
	var article Article
	err := db.Where("id = ?", articleid).First(&article).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	// user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
	// db.Create(&user)
	if err := tx.Create(&Pay{UserID: uid, ArticleID: articleid, Amount: amount}).Error; err != nil {
		tx.Rollback()
		return err
	}
	//更新用戶賬戶餘額money
	//1.首先保證賬戶存在
	// money := Money{UserID: uid}
	var money Money
	err = db.Where("user_id = ?", uid).First(&money).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	//2.用戶賬戶餘額保證大於0
	newamount := money.Amount - amount
	if newamount < 0 {
		tx.Rollback()
		return err
	}
	//3.賬戶修改餘額
	rowsAffected := tx.Model(&money).Update("amount", newamount).RowsAffected
	if rowsAffected == 0 {
		tx.Rollback()
		return nil
	}

	return tx.Commit().Error

}

連接池的問題:

//定義全局的db對象,我們執行數據庫操作主要通過他實現。
var _db *gorm.DB

func init() {
	var err error
	var dns string
	db_type := beego.AppConfig.String("db_type")
	db_name := beego.AppConfig.String("db_name")
	db_path := beego.AppConfig.String("db_path")
	if db_path == "" {
		db_path = "./"
	}

	dns = fmt.Sprintf("%s%s.db", db_path, db_name)
	_db, err = gorm.Open(db_type, dns)
	// _db.LogMode(true)
	if err != nil {
		panic("連接數據庫失敗, error=" + err.Error())
	}
	// defer gdb.Close()
	//禁止表名複數形式
	_db.SingularTable(true)
	// 開發的時候需要打開調試日誌
	// _db.LogMode(true)
	//設置數據庫連接池參數
	_db.DB().SetMaxOpenConns(100) //設置數據庫連接池最大連接數
	_db.DB().SetMaxIdleConns(20)  //連接池最大允許的空閒連接數,如果沒有sql任務需要執行的連接數大於20,超過的連接會被連接池關閉。

	_db.CreateTable(&Pay{}, &Money{}, &Recharge{})
	// if !gdb.HasTable(&Pay1{}) {
	// 	if err = gdb.CreateTable(&Pay1{}).Error; err != nil {
	// 		panic(err)
	// 	}
	// }
}

//獲取gorm db對象,其他包需要執行數據庫查詢的時候,只要通過tools.getDB()獲取db對象即可。
//不用擔心協程併發使用同樣的db對象會共用同一個連接,
// db對象在調用他的方法的時候會從數據庫連接池中獲取新的連接
// 注意:使用連接池技術後,千萬不要使用完db後調用db.Close關閉數據庫連接,
// 這樣會導致整個數據庫連接池關閉,導致連接池沒有可用的連接
func GetDB() *gorm.DB {
	return _db
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章