天天看點

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)
}           
//添加某個文章某個使用者打賞記錄
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
}           

繼續閱讀