gdbx 是一个 Go 语言数据库操作扩展库,提供通用的数据库 CRUD 操作、SQL 生成、连接池管理和多数据库适配能力。支持 MySQL、Oracle、PostgreSQL、SQLite、DM8(达梦) 五种数据库,采用依赖注入设计,与外部系统保持松耦合。
- 多数据库支持 - MySQL、Oracle、PostgreSQL、SQLite、DM8 统一 API
- 依赖注入 - 数据库连接和日志实例均支持外部注入
- 连接池管理 - 内置连接池,支持外部连接注册和过期清理
- 泛型 Repository - 通用 CRUD 操作,无需手写 SQL
- SQL Builder - 链式调用构建复杂查询
- 日志抽象 - 统一日志接口,兼容主流 Go 日志库
- Options 模式 - 灵活的配置方式
- 可扩展 - 通过
DatabaseFactory接口轻松添加新数据库适配
- Go 1.22+
- SQLite 需要 CGO 支持(
CGO_ENABLED=1)
go get github.com/dataixcom/gdbximport (
gdbx "github.com/dataixcom/gdbx"
"github.com/dataixcom/gdbx/base/config"
"github.com/dataixcom/gdbx/base/repository"
)
dsnCfg := config.DSNConfig{
DBType: config.MySQL,
Host: "localhost",
Port: 3306,
User: "root",
Password: "password",
Schema: "testdb",
MaxIdle: 5,
MaxOpen: 20,
}
repo, err := repository.NewGenericRepository(dsnCfg)
if err != nil {
log.Fatal(err)
}import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
gdbx "github.com/dataixcom/gdbx"
"github.com/dataixcom/gdbx/base/config"
"github.com/dataixcom/gdbx/base/repository"
)
db, err := sql.Open("mysql", "root:password@tcp(localhost:3306)/testdb?parseTime=true")
if err != nil {
log.Fatal(err)
}
repo, err := repository.NewGenericRepositoryWithDB(db, config.MySQL)
if err != nil {
log.Fatal(err)
}
executor, err := gdbx.NewQueryExecutor(
gdbx.WithDB(db, config.MySQL),
)import (
"log/slog"
"os"
"github.com/dataixcom/gdbx/base/logger"
"github.com/dataixcom/gdbx/base/repository"
"github.com/dataixcom/gdbx/base/template"
gdbx "github.com/dataixcom/gdbx"
)
customLogger := logger.NewLoggerFromSlog(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
})))
repo, err := repository.NewGenericRepositoryWithDB(db, config.MySQL,
repository.WithRepositoryLogger(customLogger),
)
tmpl, err := template.NewSQLExecutorTemplateWithDB(db, config.MySQL,
template.WithTemplateLogger(customLogger),
)
executor, err := gdbx.NewQueryExecutor(
gdbx.WithDB(db, config.MySQL),
gdbx.WithLogger(customLogger),
)| 数据库 | DBType 常量 | 驱动 | 标识符引用 | UPSERT 语法 | 分页语法 |
|---|---|---|---|---|---|
| MySQL | config.MySQL |
go-sql-driver/mysql | `name` |
ON DUPLICATE KEY UPDATE |
LIMIT/OFFSET |
| Oracle | config.Oracle |
go-ora/v2 | "name" |
MERGE INTO ... USING (SELECT FROM DUAL) |
ROWNUM |
| PostgreSQL | config.Postgres |
pgx/v5 | "name" |
ON CONFLICT DO UPDATE |
LIMIT/OFFSET |
| SQLite | config.SQLite |
glebarez/sqlite (纯Go) | "name" |
ON CONFLICT DO UPDATE |
LIMIT/OFFSET |
| DM8 (达梦) | config.DM8 |
gitee.com/chunanyong/dm | "name" |
MERGE INTO ... USING (SELECT FROM DUAL) |
LIMIT/OFFSET |
import (
"database/sql"
_ "github.com/glebarez/sqlite"
"github.com/dataixcom/gdbx/base/config"
"github.com/dataixcom/gdbx/base/repository"
)
// 文件数据库
dsnCfg := config.DSNConfig{
DBType: config.SQLite,
Schema: "/path/to/database.db",
}
// 内存数据库
dsnCfg := config.DSNConfig{
DBType: config.SQLite,
Schema: ":memory:",
}
// 或注入已有连接
db, _ := sql.Open("sqlite3", ":memory:")
repo, _ := repository.NewGenericRepositoryWithDB(db, config.SQLite)注意: SQLite 需要 CGO 支持。编译时需设置
CGO_ENABLED=1。默认MaxOpenConns=1以避免并发写入问题。
import (
"database/sql"
_ "gitee.com/chunanyong/dm"
"github.com/dataixcom/gdbx/base/config"
"github.com/dataixcom/gdbx/base/repository"
"github.com/dataixcom/gdbx/dm8"
)
// 通过 DSN 配置
dsnCfg := config.DSNConfig{
DBType: config.DM8,
Host: "localhost",
Port: 5236,
User: "SYSDBA",
Password: "SYSDBA001",
Schema: "TESTDB",
}
// 或注入已有连接
db, _ := sql.Open("dm", "dm://SYSDBA:SYSDBA001@localhost:5236/TESTDB")
repo, _ := repository.NewGenericRepositoryWithDB(db, config.DM8)
// 自定义驱动名称
factory := dm8.NewDM8Factory("dm8_custom")通过实现 DatabaseFactory 接口添加新数据库适配:
import (
"github.com/dataixcom/gdbx/base/config"
"github.com/dataixcom/gdbx/base/factory"
)
type MyDBFactory struct{}
func (f *MyDBFactory) CreateSQLGenerator() strategy.SQLGenerator { ... }
func (f *MyDBFactory) CreateSQLExecutor(db *sql.DB) strategy.SQLExecutor { ... }
func (f *MyDBFactory) CreateMetadataProvider(db *sql.DB) metadata.MetadataProvider { ... }
func (f *MyDBFactory) OpenDB(dsnCfg config.DSNConfig) (*sql.DB, error) { ... }
func (f *MyDBFactory) GetDBType() config.DBType { return config.DBType("mydb") }
// 注册到工厂
factory.RegisterDatabaseFactory(config.DBType("mydb"), &MyDBFactory{})gdbx 定义了 DBConnector 接口,标准库的 *sql.DB 自动满足该接口:
type DBConnector interface {
QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
PingContext(ctx context.Context) error
Close() error
SetMaxOpenConns(n int)
SetMaxIdleConns(n int)
SetConnMaxLifetime(d time.Duration)
SetConnMaxIdleTime(d time.Duration)
Stats() sql.DBStats
}err := gdbx.ValidateDBConnector(db)
if err != nil {
log.Fatalf("数据库连接无效: %v", err)
}import "github.com/dataixcom/gdbx/base/pool"
// 推荐方式:使用 ConnectionManager
cm := pool.DefaultConnectionManager()
cm.RegisterConnection("my-service-db", db, config.MySQL)
cm.RegisterConnectionWithDSN(dsnCfg, db)
err := cm.RegisterConnectionWithValidation("my-service-db", db, config.MySQL)
// 兼容方式:包级函数(委托给 DefaultConnectionManager)
pool.RegisterDBWithDSN(dsnCfg, db)
pool.RegisterDB("my-service-db", db, config.MySQL)
err := pool.RegisterDBWithValidation("my-service-db", db, config.MySQL)ConnectionManager 是统一的连接管理核心,所有包级函数均委托给全局默认 ConnectionManager 实例。
import "github.com/dataixcom/gdbx/base/pool"
// 创建自定义 ConnectionManager
cm := pool.NewConnectionManagerWithLogger(customLogger)
// 启用自动过期清理(后台 goroutine 定期清理)
cm.WithAutoCleanup(5 * time.Minute)
defer cm.StopAutoCleanup()
// 注册外部连接
cm.RegisterConnection("service-a", dbA, config.MySQL)
cm.RegisterConnection("service-b", dbB, config.DM8)
// 获取连接(自动创建或复用已有连接)
db, err := cm.GetConnection(dsnCfg)
// 健康检查
healthy, msg := cm.GetConnectionHealth(ctx, dsnCfg)
health := cm.GetAllConnectionHealth(ctx)
// 连接管理
count := cm.GetActiveConnectionCount()
removed := cm.RemoveExpiredConnections()
cm.CloseConnection(dsnCfg)
cm.CloseAll()
// 设置自定义 ConnectionManager 为全局默认
pool.SetDefaultConnectionManager(cm)
// 获取当前默认 ConnectionManager
defaultCM := pool.DefaultConnectionManager()executor, err := gdbx.NewQueryExecutor(
gdbx.WithDSNConfig(dsnCfg),
gdbx.WithPoolOptions(gdbx.PoolOptions{
MaxOpenConns: 25,
MaxIdleConns: 10,
ConnMaxLifetime: 5 * time.Minute,
ConnMaxIdleTime: 1 * time.Minute,
}),
)type Logger interface {
Debug(msg string, args ...interface{})
Info(msg string, args ...interface{})
Warn(msg string, args ...interface{})
Error(msg string, args ...interface{})
With(args ...interface{}) Logger
}| 适配器 | 说明 |
|---|---|
logger.NewLoggerFromSlog(l *slog.Logger) |
从 *slog.Logger 创建 Logger |
gdbx.WrapSlog(l *slog.Logger) |
顶层 API 包装 slog |
logger.NewNopLogger() |
静默日志(不输出) |
logger.NewDBLogger(l *slog.Logger) |
数据库专用日志(含慢查询追踪) |
logger.SetDefault(customLogger)
l := logger.GetDefault()dbLogger := logger.NewDBLogger(slog.Default(), logger.LogLevelInfo)
dbLogger.Trace(ctx, startTime, func() (string, int64) {
return sql, rowsAffected
}, err)const (
LogLevelSilent LogLevel = iota + 1 // 静默
LogLevelError // 仅错误
LogLevelWarn // 警告及以上
LogLevelInfo // 全部
)| 函数 | 说明 |
|---|---|
NewQueryExecutor(opts ...Option) |
创建 SQL 执行器 |
NewSQLGenerator(dbType) |
创建 SQL 生成器 |
NewMetadataProvider(opts ...Option) |
创建元数据提供者 |
ValidateDBConnector(db) |
验证数据库连接 |
WrapSlog(l *slog.Logger) |
包装 slog 为 Logger |
NewNopLogger() |
创建静默日志 |
| Option | 说明 |
|---|---|
WithDB(db, dbType) |
注入外部数据库连接 |
WithDSNConfig(dsnCfg) |
使用 DSN 配置自动创建连接 |
WithLogger(l) |
注入 Logger 实例 |
WithSlogLogger(l) |
注入 *slog.Logger |
WithPoolOptions(opts) |
配置连接池参数 |
repo, _ := repository.NewGenericRepository(dsnCfg)
repo, _ := repository.NewGenericRepositoryWithDB(db, dbType, WithRepositoryLogger(l))
results, err := repo.FindAll(selectCfg)
result, err := repo.FindById(selectCfg)
affected, err := repo.Insert(insertCfg)
affected, err := repo.Update(updateCfg)
affected, err := repo.Delete(deleteCfg)
count, err := repo.Count(selectCfg)
exists, err := repo.Exists(selectCfg)
affected, err := repo.BatchInsert(batchInsertCfg)
affected, err := repo.BatchUpdate(batchUpdateCfg)
affected, err := repo.Upsert(upsertCfg)
affected, err := repo.BatchUpsert(batchUpsertCfg)
pageResult, err := repo.PageQuery(pageCfg)
results, err := repo.ExecuteRawQuery(sql)
affected, err := repo.ExecuteRawExec(sql)
repo.SetLogger(customLogger)
l := repo.GetLogger()| 方法 | 说明 |
|---|---|
NewConnectionManager() |
创建连接管理器 |
NewConnectionManagerWithLogger(l) |
创建带日志的连接管理器 |
cm.RegisterConnection(key, db, dbType) |
注册外部连接 |
cm.RegisterConnectionWithDSN(dsnCfg, db) |
通过 DSN 注册连接 |
cm.RegisterConnectionWithValidation(key, db, dbType) |
带验证的注册 |
cm.UnregisterConnection(key) |
取消注册 |
cm.GetConnection(dsnCfg) |
获取连接(自动创建或复用) |
cm.GetConnectionWithContext(ctx, dsnCfg) |
带上下文获取连接 |
cm.GetActiveConnectionCount() |
获取活跃连接数 |
cm.RemoveExpiredConnections() |
清理过期连接 |
cm.CloseConnection(dsnCfg) |
关闭指定连接 |
cm.CloseAll() |
关闭所有连接 |
cm.Ping(ctx, dsnCfg) |
检查连接可用性 |
cm.GetConnectionHealth(ctx, dsnCfg) |
获取连接健康状态 |
cm.GetAllConnectionHealth(ctx) |
获取所有连接健康状态 |
cm.WithAutoCleanup(interval) |
启用自动过期清理 |
cm.StopAutoCleanup() |
停止自动清理 |
cm.SetLogger(l) |
设置日志实例 |
DefaultConnectionManager() |
获取全局默认 ConnectionManager |
SetDefaultConnectionManager(cm) |
设置全局默认 ConnectionManager |
| 函数 | 说明 |
|---|---|
RegisterDB(key, db, dbType) |
注册外部连接(Deprecated) |
RegisterDBWithDSN(dsnCfg, db) |
通过 DSN 注册连接(Deprecated) |
RegisterDBWithValidation(key, db, dbType) |
带验证的注册(Deprecated) |
UnregisterDB(key) |
取消注册(Deprecated) |
GetDBPool(dsnCfg) |
获取连接池(Deprecated) |
GetDBPoolWithContext(ctx, dsnCfg) |
带上下文获取连接池(Deprecated) |
GetDBConnection(dsnCfg) |
获取连接(Deprecated) |
GetActiveConnectionCount() |
获取活跃连接数(Deprecated) |
RemoveExpiredConnections() |
清理过期连接(Deprecated) |
CloseAllConnections() |
关闭所有连接(Deprecated) |
gdbx/
├── gdbx.go # 顶层 API,Options 模式,DBConnector 接口
├── base/
│ ├── config/ # 数据库配置,DSN,Where 子句构建
│ ├── logger/ # 日志接口,适配器,DBLogger
│ ├── pool/ # 连接池管理,ConnectionManager
│ ├── factory/ # 数据库工厂模式
│ ├── repository/ # 通用 Repository
│ ├── template/ # SQL 执行模板
│ ├── strategy/ # SQL 生成和执行策略
│ ├── builder/ # SQL Builder
│ ├── adapter/ # 数据库适配器
│ ├── decorator/ # 查询装饰器
│ ├── metadata/ # 数据库元数据
│ ├── observer/ # 事件观察者
│ └── utils/ # 工具函数
├── mysql/ # MySQL 适配器
├── oracle/ # Oracle 适配器
├── postgres/ # PostgreSQL 适配器
├── sqlite/ # SQLite 适配器
├── dm8/ # DM8(达梦)适配器
└── examples/ # 示例代码
├── di_injection/ # 依赖注入示例
├── sqlite_demo/ # SQLite 使用示例
├── dm8_demo/ # DM8 使用示例
├── multi_db/ # 多数据库示例
├── sql_builder/ # SQL Builder 示例
└── where_clause/ # Where 子句示例
推荐使用 WithDB 注入已有的数据库连接:
db := myApp.GetDB()
repo, _ := repository.NewGenericRepositoryWithDB(db, config.MySQL,
repository.WithRepositoryLogger(myApp.GetLogger()),
)jsonLogger := logger.NewLoggerFromSlog(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
})))
fileLogger, _ := logger.NewFileLogger("/var/log/gdbx.log")
rotateLogger, _ := logger.NewRotatingFileLogger("/var/log/gdbx.log", 100)nopLogger := logger.NewNopLogger()
repo.SetLogger(nopLogger)目前支持 MySQL、Oracle、PostgreSQL、SQLite 和 DM8(达梦)。可通过实现 factory.DatabaseFactory 接口扩展其他数据库。
项目已使用纯 Go 实现的 SQLite 驱动 github.com/glebarez/sqlite,无需 CGO 支持。可直接编译:
go build ./...如需切换回 CGO 驱动,修改 sqlite/sqlite_factory.go 中的导入即可。
DM8 驱动需要单独安装。推荐使用 dm8.NewDM8Factory(driverName) 指定驱动名称,并通过 database/sql.Open 注入已有连接:
import _ "gitee.com/chunanyong/dm"
db, _ := sql.Open("dm", "dm://SYSDBA:password@host:5236/schema")
repo, _ := repository.NewGenericRepositoryWithDB(db, config.DM8)go test -tags=integration ./...不会。通过 RegisterConnection 注册的外部连接(External=true)在 CloseAll 和 RemoveExpiredConnections 时不会被关闭,需要由注册方自行管理生命周期。
包级函数(如 GetDBPool、RegisterDB)已标记为 Deprecated,它们内部委托给全局默认 ConnectionManager 实例。推荐直接使用 ConnectionManager,它提供更完整的功能(自动清理、健康检查、并发安全的连接创建等)。可通过 pool.DefaultConnectionManager() 获取全局默认实例,或通过 pool.SetDefaultConnectionManager(cm) 设置自定义实例。
MIT License