Files
server/app/utils/gorm_sharding.go
2026-01-16 15:49:34 +08:00

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 实例")
}