72 lines
2.1 KiB
Go
72 lines
2.1 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"sync"
|
|
|
|
"github.com/goravel/framework/facades"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
var (
|
|
gormDBInstance *gorm.DB
|
|
gormDBOnce sync.Once
|
|
gormDBErr error
|
|
)
|
|
|
|
// GetGormDB 获取原生 GORM DB 实例
|
|
// 通过框架的 Query().Instance() 方法获取 GORM DB 实例
|
|
// 使用单例模式,确保只获取一次
|
|
func GetGormDB() (*gorm.DB, error) {
|
|
gormDBOnce.Do(func() {
|
|
gormDBInstance, gormDBErr = tryGetGormFromFramework()
|
|
if gormDBErr == nil && gormDBInstance != nil {
|
|
facades.Log().Infof("成功从框架获取 GORM DB 实例")
|
|
}
|
|
})
|
|
return gormDBInstance, gormDBErr
|
|
}
|
|
|
|
// tryGetGormFromFramework 尝试从框架的 ORM 获取底层 GORM DB 实例
|
|
// 通过 Query().Instance() 方法获取 GORM DB 实例
|
|
func tryGetGormFromFramework() (*gorm.DB, error) {
|
|
orm := facades.Orm()
|
|
if orm == nil {
|
|
return nil, fmt.Errorf("框架 ORM 不可用")
|
|
}
|
|
|
|
ormValue := reflect.ValueOf(orm)
|
|
|
|
// 通过 Query() 方法获取查询对象,然后调用 Instance() 方法获取 GORM DB
|
|
if queryMethod := ormValue.MethodByName("Query"); queryMethod.IsValid() {
|
|
queryResults := queryMethod.Call(nil)
|
|
if len(queryResults) > 0 {
|
|
queryValue := queryResults[0]
|
|
if queryValue.Kind() == reflect.Interface && !queryValue.IsNil() {
|
|
if queryElem := queryValue.Elem(); queryElem.IsValid() {
|
|
// 调用 Instance() 方法
|
|
if instanceMethod := queryElem.MethodByName("Instance"); instanceMethod.IsValid() {
|
|
methodType := instanceMethod.Type()
|
|
if methodType.NumIn() == 0 && methodType.NumOut() > 0 {
|
|
results := instanceMethod.Call(nil)
|
|
if len(results) > 0 {
|
|
result := results[0]
|
|
// 检查返回类型是否为 *gorm.DB
|
|
if result.Type().String() == "*gorm.DB" && !result.IsNil() {
|
|
if db, ok := result.Interface().(*gorm.DB); ok && db != nil {
|
|
facades.Log().Infof("成功通过 Instance() 方法从 Query 对象获取 GORM DB 实例")
|
|
return db, nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("无法从框架获取 GORM DB 实例")
|
|
}
|