github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/extend/orm/xorm.go (about)

     1  package orm
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"github.com/isyscore/isc-gobase/bean"
     7  	"github.com/isyscore/isc-gobase/config"
     8  	"github.com/isyscore/isc-gobase/constants"
     9  	"github.com/isyscore/isc-gobase/listener"
    10  	"github.com/isyscore/isc-gobase/logger"
    11  	"time"
    12  	"xorm.io/xorm"
    13  	"xorm.io/xorm/contexts"
    14  	"xorm.io/xorm/log"
    15  )
    16  
    17  type GobaseXormHook interface {
    18  	BeforeProcess(c *contexts.ContextHook, driverName string) (context.Context, error)
    19  	AfterProcess(c *contexts.ContextHook, driverName string) error
    20  }
    21  
    22  var defaultXormHooks []DefaultXormHook
    23  
    24  type DefaultXormHook struct {
    25  	driverName string
    26  	gobaseXormHook GobaseXormHook
    27  }
    28  
    29  func (defaultHook *DefaultXormHook)BeforeProcess(c *contexts.ContextHook) (context.Context, error) {
    30  	return defaultHook.gobaseXormHook.BeforeProcess(c, defaultHook.driverName)
    31  }
    32  
    33  func (defaultHook *DefaultXormHook)AfterProcess(c *contexts.ContextHook) error {
    34  	return defaultHook.gobaseXormHook.AfterProcess(c, defaultHook.driverName)
    35  }
    36  
    37  func init() {
    38  	defaultXormHooks = []DefaultXormHook{}
    39  }
    40  
    41  func NewXormDb() (*xorm.Engine, error) {
    42  	return doNewXormDb("", map[string]string{})
    43  }
    44  
    45  func NewXormDbWithParams(params map[string]string) (*xorm.Engine, error) {
    46  	return doNewXormDb("", params)
    47  }
    48  
    49  func NewXormDbWithName(datasourceName string) (*xorm.Engine, error) {
    50  	return doNewXormDb(datasourceName, map[string]string{})
    51  }
    52  
    53  func NewXormDbWithNameParams(datasourceName string, params map[string]string) (*xorm.Engine, error) {
    54  	return doNewXormDb(datasourceName, params)
    55  }
    56  
    57  func AddXormHook(hook GobaseXormHook) {
    58  	defaultXormHook := DefaultXormHook{gobaseXormHook: hook}
    59  	defaultXormHooks = append(defaultXormHooks, defaultXormHook)
    60  	xormDbs := bean.GetBeanWithNamePre(constants.BeanNameXormPre)
    61  	if xormDbs == nil {
    62  		return
    63  	}
    64  	for _, db := range xormDbs {
    65  		db.(*xorm.Engine).AddHook(&defaultXormHook)
    66  	}
    67  }
    68  
    69  func doNewXormDb(datasourceName string, params map[string]string) (*xorm.Engine, error) {
    70  	datasourceConfig := config.DatasourceConfig{}
    71  	targetDatasourceName := "base.datasource"
    72  	if datasourceName != "" {
    73  		targetDatasourceName = "base.datasource." + datasourceName
    74  	}
    75  	err := config.GetValueObject(targetDatasourceName, &datasourceConfig)
    76  	if err != nil {
    77  		logger.Warn("读取读取配置【datasource】异常")
    78  		return nil, err
    79  	}
    80  
    81  	var dsn = getDbDsn(datasourceConfig.DriverName, datasourceConfig)
    82  	var xormDb *xorm.Engine
    83  	xormDb, err = xorm.NewEngineWithParams(datasourceConfig.DriverName, dsn, params)
    84  	if err != nil {
    85  		logger.Warn("获取数据库db异常:%v", err.Error())
    86  		return nil, err
    87  	}
    88  
    89  	for _, hook := range defaultXormHooks {
    90  		hook.driverName = datasourceConfig.DriverName
    91  		xormDb.AddHook(&hook)
    92  	}
    93  
    94  	maxIdleConns := config.GetValueInt("base.datasource.connect-pool.max-idle-conns")
    95  	if maxIdleConns != 0 {
    96  		// 设置空闲的最大连接数
    97  		xormDb.SetMaxIdleConns(maxIdleConns)
    98  	}
    99  
   100  	maxOpenConns := config.GetValueInt("base.datasource.connect-pool.max-open-conns")
   101  	if maxOpenConns != 0 {
   102  		// 设置数据库打开连接的最大数量
   103  		xormDb.SetMaxOpenConns(maxOpenConns)
   104  	}
   105  
   106  	maxLifeTime := config.GetValueString("base.datasource.connect-pool.max-life-time")
   107  	if maxLifeTime != "" {
   108  		// 设置连接可重复使用的最大时间
   109  		t, err := time.ParseDuration(maxLifeTime)
   110  		if err != nil {
   111  			logger.Warn("读取配置【base.datasource.connect-pool.max-life-time】异常", err)
   112  		} else {
   113  			xormDb.SetConnMaxLifetime(t)
   114  		}
   115  	}
   116  
   117  	xormDb.ShowSQL(true)
   118  	xormDb.SetLogger(&XormLoggerAdapter{})
   119  	bean.AddBean(constants.BeanNameXormPre + datasourceName, xormDb)
   120  
   121  	// 添加orm的配置监听器
   122  	listener.AddListener(listener.EventOfConfigChange, ConfigChangeListenerOfOrm)
   123  	return xormDb, nil
   124  }
   125  
   126  func NewXormDbMasterSlave(masterDatasourceName string, slaveDatasourceNames []string, policies ...xorm.GroupPolicy) (*xorm.EngineGroup, error) {
   127  	masterDb, err := NewXormDbWithName(masterDatasourceName)
   128  	if err != nil {
   129  		logger.Warn("获取数据库 主节点【%v】失败,%v", masterDatasourceName, err.Error())
   130  		return nil, err
   131  	}
   132  
   133  	var slaveDbs []*xorm.Engine
   134  	for _, slaveDatasource := range slaveDatasourceNames {
   135  		slaveDb, err := NewXormDbWithName(slaveDatasource)
   136  		if err != nil {
   137  			logger.Warn("获取数据库 从节点【%v】失败,%v", slaveDatasource, err.Error())
   138  			return nil, err
   139  		}
   140  
   141  		slaveDbs = append(slaveDbs, slaveDb)
   142  	}
   143  
   144  	return xorm.NewEngineGroup(masterDb, slaveDbs, policies...)
   145  }
   146  
   147  // LoggerAdapter wraps a Logger interface as LoggerContext interface
   148  type XormLoggerAdapter struct {
   149  }
   150  
   151  // BeforeSQL implements ContextLogger
   152  func (l *XormLoggerAdapter) BeforeSQL(ctx log.LogContext) {}
   153  
   154  // AfterSQL implements ContextLogger
   155  func (l *XormLoggerAdapter) AfterSQL(ctx log.LogContext) {
   156  	var sessionPart string
   157  	v := ctx.Ctx.Value("__xorm_session_id")
   158  	if key, ok := v.(string); ok {
   159  		sessionPart = fmt.Sprintf(" [%s]", key)
   160  	}
   161  	if ctx.ExecuteTime > 0 {
   162  		logger.Group("orm").Debugf("[SQL]%s %s %v - %v", sessionPart, ctx.SQL, ctx.Args, ctx.ExecuteTime)
   163  	} else {
   164  		logger.Group("orm").Debugf("[SQL]%s %s %v", sessionPart, ctx.SQL, ctx.Args)
   165  	}
   166  }
   167  
   168  // Debugf implements ContextLogger
   169  func (l *XormLoggerAdapter) Debugf(format string, v ...interface{}) {
   170  	logger.Group("orm").Debug(format, v)
   171  }
   172  
   173  // Errorf implements ContextLogger
   174  func (l *XormLoggerAdapter) Errorf(format string, v ...interface{}) {
   175  	logger.Error(format, v)
   176  }
   177  
   178  // Infof implements ContextLogger
   179  func (l *XormLoggerAdapter) Infof(format string, v ...interface{}) {
   180  	logger.Info(format, v)
   181  }
   182  
   183  // Warnf implements ContextLogger
   184  func (l *XormLoggerAdapter) Warnf(format string, v ...interface{}) {
   185  	logger.Warn(format, v)
   186  }
   187  
   188  // Level implements ContextLogger
   189  func (l *XormLoggerAdapter) Level() log.LogLevel {
   190  	return log.LOG_INFO
   191  }
   192  
   193  // SetLevel implements ContextLogger
   194  func (l *XormLoggerAdapter) SetLevel(lv log.LogLevel) {
   195  }
   196  
   197  // ShowSQL implements ContextLogger
   198  func (l *XormLoggerAdapter) ShowSQL(show ...bool) {
   199  
   200  }
   201  
   202  // IsShowSQL implements ContextLogger
   203  func (l *XormLoggerAdapter) IsShowSQL() bool {
   204  	return true
   205  }
   206