This commit is contained in:
邹宗楠
2022-08-11 14:23:06 +08:00
parent 7efcd3a614
commit c845eabe69
32 changed files with 231 additions and 212 deletions

307
business/dao/dao.go Normal file
View File

@@ -0,0 +1,307 @@
package dao
import (
"errors"
"reflect"
"runtime/debug"
"time"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/globals"
"github.com/astaxie/beego/client/orm"
)
const (
useGetRowsWhenGetRow = true
transactionWarningSeconds = 10 * 60 // 5分钟
)
type DaoDB struct {
transactionLevel int
Db orm.Ormer
transactionWatchTimer *time.Timer
beginTransactionStack []byte
}
// func GetRows(db *gorm.DB, inPtr interface{}, sql string, values ...interface{}) (err error) {
// if db == nil {
// db = gormdb.GetDB()
// }
// topTypeInfo := reflect.TypeOf(inPtr)
// if topTypeInfo.Kind() != reflect.Ptr {
// panic("SelectEntities inPtr should be slice ptr (*[]Type)")
// }
// typeInfo := topTypeInfo.Elem()
// if typeInfo.Kind() != reflect.Slice {
// panic("SelectEntities inPtr should be slice ptr (*[]Type)")
// }
// elmType := typeInfo.Elem()
// valueInfo := reflect.ValueOf(inPtr)
// rows, err := db.Raw(sql, values...).Rows()
// if err == nil {
// defer rows.Close()
// for rows.Next() {
// var value reflect.Value
// if elmType.Kind() == reflect.Ptr {
// value = reflect.New(elmType.Elem())
// } else {
// value = reflect.New(elmType)
// }
// db.ScanRows(rows, value.Interface())
// if elmType.Kind() != reflect.Ptr {
// value = value.Elem()
// }
// valueInfo.Elem().Set(reflect.Append(valueInfo.Elem(), value))
// }
// return nil
// }
// return err
// }
// beego orm的对于传代表字段的字串数据库字段名完全匹配区分大小写结构体字段名不区分大小写都可以
func GetDB() *DaoDB {
return &DaoDB{Db: orm.NewOrm()}
}
func Begin(db *DaoDB) (txDB orm.TxOrmer, err error) {
if db.transactionLevel == 0 {
txDB, err = db.Db.Begin()
if err == nil {
db.startWatchTransaction()
}
}
db.transactionLevel++
return txDB, err
}
func (db *DaoDB) startWatchTransaction() {
db.beginTransactionStack = debug.Stack()
db.transactionWatchTimer = utils.AfterFuncWithRecover(transactionWarningSeconds*time.Second, func() {
globals.SugarLogger.Warnf("Begin Transaction too long, %s", string(db.beginTransactionStack))
db.transactionWatchTimer = nil
db.beginTransactionStack = nil
})
}
func (db *DaoDB) stopWatchTransaction() {
if db.transactionWatchTimer != nil {
db.transactionWatchTimer.Stop()
db.transactionWatchTimer = nil
db.beginTransactionStack = nil
}
}
func Commit(db *DaoDB, txDB orm.TxOrmer) (err error) {
if db.transactionLevel == 1 {
db.stopWatchTransaction()
err = txDB.Commit()
//err = db.Db.Commit()
db.transactionLevel = 0
} else if db.transactionLevel > 1 {
db.transactionLevel--
}
return err
}
func Rollback(db *DaoDB, txDB orm.TxOrmer) (err error) {
if db.transactionLevel > 0 {
db.stopWatchTransaction()
err = txDB.Rollback()
//err = db.Db.Rollback()
}
db.transactionLevel = 0
return err
}
func GetRow(db *DaoDB, inPtr interface{}, sql string, values ...interface{}) (err error) {
if db == nil {
db = GetDB()
}
if !useGetRowsWhenGetRow { // beego QueryRow有bug嵌入的struct不能正常绑定
err = db.Db.Raw(sql, values).QueryRow(inPtr)
} else {
typeInfo := reflect.TypeOf(inPtr)
if typeInfo.Kind() != reflect.Ptr {
return errors.New("inPtr must be ptr")
}
slice := reflect.New(reflect.SliceOf(typeInfo.Elem()))
if err = GetRows(db, slice.Interface(), sql, values...); err == nil {
slice = slice.Elem()
if slice.Len() > 0 {
reflect.ValueOf(inPtr).Elem().Set(slice.Index(0))
} else {
return orm.ErrNoRows
}
}
}
return err
}
func GetRowTx(txDB orm.TxOrmer, inPtr interface{}, sql string, values ...interface{}) (err error) {
if txDB == nil {
return
}
if !useGetRowsWhenGetRow { // beego QueryRow有bug嵌入的struct不能正常绑定
err = txDB.Raw(sql, values).QueryRow(inPtr)
//err = db.Db.Raw(sql, values).QueryRow(inPtr)
} else {
typeInfo := reflect.TypeOf(inPtr)
if typeInfo.Kind() != reflect.Ptr {
return errors.New("inPtr must be ptr")
}
slice := reflect.New(reflect.SliceOf(typeInfo.Elem()))
if err = GetRowsTx(txDB, slice.Interface(), sql, values...); err == nil {
slice = slice.Elem()
if slice.Len() > 0 {
reflect.ValueOf(inPtr).Elem().Set(slice.Index(0))
} else {
return orm.ErrNoRows
}
}
}
return err
}
func GetRows(db *DaoDB, inPtr interface{}, sql string, values ...interface{}) (err error) {
if db == nil {
db = GetDB()
}
_, err = db.Db.Raw(sql, values).QueryRows(inPtr)
return err
}
func GetRowsTx(txDB orm.TxOrmer, inPtr interface{}, sql string, values ...interface{}) (err error) {
if txDB == nil {
return
}
_, err = txDB.Raw(sql, values).QueryRows(inPtr)
//_, err = db.Db.Raw(sql, values).QueryRows(inPtr)
return err
}
func GetEntity(db *DaoDB, item interface{}, cols ...string) (err error) {
if db == nil {
db = GetDB()
}
err = utils.CallFuncLogErrorIgnore(func() error {
return db.Db.Read(item, cols...)
}, reflect.TypeOf(item).Name(), orm.ErrNoRows)
return err
}
func UpdateEntity(db *DaoDB, item interface{}, cols ...string) (num int64, err error) {
if db == nil {
db = GetDB()
}
num, err = db.Db.Update(item, cols...)
if err != nil && !IsDuplicateError(err) {
globals.SugarLogger.Errorf("UpdateEntity %s failed with error:%v", reflect.TypeOf(item).Name(), err)
}
return num, err
}
func CreateEntity(db *DaoDB, item interface{}) (err error) {
if db == nil {
db = GetDB()
}
if _, err = db.Db.Insert(item); err != nil && !IsDuplicateError(err) {
globals.SugarLogger.Errorf("CreateEntity %s failed with error:%v", reflect.TypeOf(item).Name(), err)
}
return err
}
func UpdateEntityTx(txDB orm.TxOrmer, item interface{}, cols ...string) (num int64, err error) {
if txDB == nil {
return
}
num, err = txDB.Update(item, cols...)
if err != nil && !IsDuplicateError(err) {
globals.SugarLogger.Errorf("UpdateEntity %s failed with error:%v", reflect.TypeOf(item).Name(), err)
}
return num, err
}
func CreateEntityTx(txDB orm.TxOrmer, item interface{}) (err error) {
if txDB == nil {
return
}
if _, err = txDB.Insert(item); err != nil && !IsDuplicateError(err) {
globals.SugarLogger.Errorf("CreateEntity %s failed with error:%v", reflect.TypeOf(item).Name(), err)
}
return err
}
// InsertMulti执行成功后ID不会改写成正确的象Insert一样
func CreateMultiEntities(db *DaoDB, item interface{}) (err error) {
if db == nil {
db = GetDB()
}
if _, err = db.Db.InsertMulti(20, item); err != nil && !IsDuplicateError(err) {
globals.SugarLogger.Errorf("CreateEntity %s failed with error:%v", reflect.TypeOf(item).Name(), err)
}
return err
}
func CreateOrUpdate(db *DaoDB, item interface{}, colConflitAndArgs ...string) (err error) {
if db == nil {
db = GetDB()
}
_, err = db.Db.InsertOrUpdate(item, colConflitAndArgs...)
return err
}
func DeleteEntity(db *DaoDB, item interface{}, cols ...string) (num int64, err error) {
if db == nil {
db = GetDB()
}
err = utils.CallFuncLogError(func() error {
num, err = db.Db.Delete(item, cols...)
return err
}, reflect.TypeOf(item).Name())
return num, err
}
func DeleteEntityTx(txDB orm.TxOrmer, item interface{}, cols ...string) (num int64, err error) {
if txDB == nil {
return
}
err = utils.CallFuncLogError(func() error {
num, err = txDB.Delete(item, cols...)
//num, err = db.Db.Delete(item, cols...)
return err
}, reflect.TypeOf(item).Name())
return num, err
}
func ExecuteSQL(db *DaoDB, sql string, params ...interface{}) (num int64, err error) {
if db == nil {
db = GetDB()
}
err = utils.CallFuncLogError(func() error {
result, err2 := db.Db.Raw(sql, params...).Exec()
if err2 == nil {
num, _ = result.RowsAffected()
}
return err2
}, sql)
return num, err
}
// 此函数要求db在事务中否则可能导致取得到的是另一个连接的数据
func GetLastTotalRowCount(db *DaoDB) int {
countInfo := &struct{ Ct int }{}
if err := GetRow(db, countInfo, "SELECT FOUND_ROWS() ct"); err == nil {
return countInfo.Ct
}
return 0
}
func GetLastTotalRowCountTx(txDB orm.TxOrmer) int {
countInfo := &struct{ Ct int }{}
if err := GetRowTx(txDB, countInfo, "SELECT FOUND_ROWS() ct"); err == nil {
return countInfo.Ct
}
return 0
}