sqlbuilder

package module
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 28, 2025 License: Apache-2.0 Imports: 3 Imported by: 0

README

go-sqlbuilder

GitHub go.mod Go version GoDoc License

一个功能丰富、高性能的 Go 语言 GORM 仓储层封装库,提供类型安全的 CRUD 操作、复杂查询构建和便利方法。

✨ 特性

  • 🚀 仓储模式:泛型 BaseRepository 和 EnhancedRepository,类型安全的 CRUD 操作
  • 🔍 高级查询:FilterGroup 支持复杂的 AND/OR 条件组合和无限嵌套
  • 🎯 类型安全:完全的泛型支持,编译时类型检查
  • 📊 性能优化:批量操作、游标分页、原子字段更新
  • 🔐 错误处理:集成 go-toolbox/errorx 的结构化错误管理
  • 📝 审计追踪:内置审计字段(created_by, updated_by)
  • 🛠️ 便利方法:常用操作的快捷方法

📦 安装

go get github.com/kamalyes/go-sqlbuilder

🚀 快速开始

package main

import (
    "context"
    "log"
    
    "github.com/kamalyes/go-sqlbuilder/db"
    "github.com/kamalyes/go-sqlbuilder/repository"
    "github.com/kamalyes/go-logger"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

type User struct {
    repository.BaseModel
    Name   string `gorm:"type:varchar(100)"`
    Email  string `gorm:"type:varchar(100);uniqueIndex"`
    Age    int    `gorm:"type:int"`
    Status string `gorm:"type:varchar(20)"`
}

func main() {
    // 1. 连接数据库
    dsn := "user:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True"
    gormDB, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        log.Fatal(err)
    }
    
    // 2. 创建 Handler
    handler, err := db.NewGormHandler(gormDB)
    if err != nil {
        log.Fatal(err)
    }
    
    // 3. 创建 Repository
    logger := logger.NewLogger(nil)
    repo := repository.NewBaseRepository[User](handler, logger, "users")
    
    ctx := context.Background()
    
    // 4. 使用 Repository
    
    // 创建
    user := &User{Name: "张三", Email: "zhangsan@example.com", Age: 25}
    created, err := repo.Create(ctx, user)
    
    // 查询
    user, err = repo.Get(ctx, 1)
    
    // 更新
    user.Age = 26
    updated, err := repo.Update(ctx, user)
    
    // 删除
    err = repo.Delete(ctx, 1)
}

📚 核心功能

BaseRepository - 完整 CRUD

提供所有基础数据库操作:

repo := repository.NewBaseRepository[User](handler, logger, "users")

// 创建操作
user, err := repo.Create(ctx, &User{Name: "Alice"})
err = repo.CreateBatch(ctx, users...)
created, isNew, err := repo.CreateIfNotExists(ctx, user, "email")

// 查询操作
user, err := repo.Get(ctx, 1)
users, err := repo.GetAll(ctx)
users, paging, err := repo.ListWithPagination(ctx, query, paging)

// 更新操作
user, err := repo.Update(ctx, user)
err = repo.UpdateFields(ctx, 1, map[string]interface{}{"age": 30})

// 删除操作
err = repo.Delete(ctx, 1)
err = repo.SoftDelete(ctx, 1, "deleted_at", time.Now())

// 统计操作
count, err := repo.Count(ctx)
exists, err := repo.Exists(ctx, filter)
便捷查询构建 🔥 新功能

支持链式调用的查询构建,让代码更简洁直观:

// 现在可以这样链式调用构建查询条件
query := repository.NewQuery().
    AddEqual("status", 1).
    AddLike("name", "test").
    AddTimeAfter("created_at", time.Now().AddDate(0, -1, 0)).
    AddIn("category_id", 1, 2, 3).
    AddOrderDesc("created_at").
    Take(10)

users, err := repo.List(ctx, query)

// 使用时间便捷方法
query := repository.NewQuery().
    AddEqual("status", 1).
    AddThisMonth("created_at").
    AddOrderDesc("id")

users, err := repo.List(ctx, query)

// 复杂条件组合
query := repository.NewQuery().
    AddEqual("status", 1).
    AddStartsWith("name", "user_").
    AddBetween("age", 18, 65).
    AddIsNotNull("email").
    Page(1, 20)

users, pagination, err := repo.ListWithPagination(ctx, query, nil)
便捷方法对照表
传统方式 便捷方法 说明
AddFilter(NewEqFilter("field", value)) AddEqual("field", value) 等于条件
AddFilter(NewLikeFilter("field", "%test%")) AddLike("field", "test") 模糊匹配
AddFilter(NewGtFilter("field", value)) AddGreaterThan("field", value) 大于条件
AddOrder("field", "DESC") AddOrderDesc("field") 降序排序
WithPaging(1, 20) Page(1, 20) 分页设置
EnhancedRepository - 便利方法

扩展方法提供更便捷的操作:

enhanced := repository.NewEnhancedRepository[User](handler, logger, "users")

// 字段查询
users, err := enhanced.FindByField(ctx, "status", "active")

// 游标分页(大数据量性能更好)
users, cursor, err := enhanced.FindByFieldWithCursor(ctx, "status", "active", "", 20, "id", "ASC")

// 原子字段操作
err = enhanced.IncrementField(ctx, 1, "points", 10)      // 积分 +10
err = enhanced.DecrementField(ctx, 1, "stock", 5)        // 库存 -5
err = enhanced.ToggleField(ctx, 1, "is_active")          // 切换布尔值
FilterGroup - 复杂查询

支持任意复杂的 AND/OR 条件组合:

import (
    "github.com/kamalyes/go-sqlbuilder/constants"
    "github.com/kamalyes/go-sqlbuilder/repository"
)

// 查询条件:(status = 'active' OR status = 'trial') AND age > 18
statusGroup := repository.NewFilterGroup(constants.AND_OR).
    AddFilter(repository.NewEqFilter("status", "active")).
    AddFilter(repository.NewEqFilter("status", "trial"))

mainGroup := repository.NewFilterGroup(constants.AND_AND).
    AddGroup(statusGroup).
    AddFilter(repository.NewGtFilter("age", 18))

query := repository.NewQuery().SetFilterGroup(mainGroup)
users, err := repo.List(ctx, query)
丰富的过滤器
// 比较操作
repository.NewEqFilter("status", "active")              // =
repository.NewGtFilter("age", 18)                       // >
repository.NewBetweenFilter("price", 100, 1000)         // BETWEEN

// 范围操作
repository.NewInFilter("id", []interface{}{1, 2, 3})    // IN
repository.NewNotInFilter("status", []interface{}{"deleted", "banned"})

// 模糊查询
repository.NewLikeFilter("name", "张")                  // LIKE '%张%'

// NULL 检查
repository.NewIsNullFilter("deleted_at")                // IS NULL
repository.NewIsNotNullFilter("verified_at")            // IS NOT NULL

// 时间范围
repository.NewTodayFilter("created_at")                 // 今天
repository.NewThisWeekFilter("created_at")              // 本周
repository.NewLastMonthFilter("created_at")             // 上月

// 自定义 SQL
repository.NewCustomFilter("YEAR(created_at) = ?", 2024)

📖 完整文档

我们提供了详细的模块化文档:

🏗️ 内置模型

BaseModel

包含基础字段的模型:

type User struct {
    repository.BaseModel  // ID, CreatedAt, UpdatedAt, DeletedAt
    Name  string
    Email string
}
AuditModel

包含审计字段的模型:

type Article struct {
    repository.AuditModel  // BaseModel + CreatedBy, UpdatedBy
    Title   string
    Content string
}

⚙️ 配置选项

repo := repository.NewBaseRepository[User](
    handler,
    logger,
    "users",
    repository.WithBatchSize[User](200),              // 批处理大小
    repository.WithTimeout[User](60),                 // 超时时间
    repository.WithDefaultPreloads[User]("Profile"),  // 默认预加载
    repository.WithDefaultOrder[User]("id DESC"),     // 默认排序
)

🧪 测试

# 运行所有测试
go test ./... -v

# 测试覆盖率
go test ./... -cover
go test -coverprofile=coverage -covermode=atomic
go tool cover -func=coverage
go test ./repository -coverprofile=coverage.out; go tool cover -html=coverage.out -o coverage.html
go tool cover -func=coverage | findstr -v "100.0%"

# 运行特定测试
go test -v -run TestBaseRepository

📦 依赖

🤝 贡献

欢迎贡献!请随时提交 Pull Request。

  1. Fork 本仓库
  2. 创建特性分支 (git checkout -b feature/amazing-feature)
  3. 提交更改 (git commit -m 'Add some amazing feature')
  4. 推送到分支 (git push origin feature/amazing-feature)
  5. 开启 Pull Request

📄 许可证

本项目采用 MIT 许可证 - 详见 LICENSE 文件

👨‍💻 作者

Kamal Yang (@kamalyes)

🙏 致谢

  • GORM 团队提供的优秀 ORM
  • Go 社区的灵感和支持

Documentation

Overview

* @Author: kamalyes 501893067@qq.com * @Date: 2025-11-11 00:00:00 * @LastEditors: kamalyes 501893067@qq.com * @LastEditTime: 2025-11-23 22:50:00 * @FilePath: \go-sqlbuilder\mapopt.go * @Description: Map类型扩展 - MapAny、MapString、StringSlice的数据库序列化和泛型操作 * * Copyright (c) 2025 by kamalyes, All Rights Reserved.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type JSONType added in v0.1.7

type JSONType[T any] struct {
	Data T
}

泛型 JSON 类型,支持任意可序列化类型

func (*JSONType[T]) Get added in v0.1.7

func (j *JSONType[T]) Get() T

Get 获取数据

func (*JSONType[T]) Scan added in v0.1.7

func (j *JSONType[T]) Scan(value interface{}) error

func (*JSONType[T]) Set added in v0.1.7

func (j *JSONType[T]) Set(data T)

Set 设置数据

func (JSONType[T]) Value added in v0.1.7

func (j JSONType[T]) Value() (driver.Value, error)

type MapAny

type MapAny map[string]any

MapAny 任意类型的 Map,支持数据库 JSON 序列化

func (MapAny) Clone added in v0.1.7

func (m MapAny) Clone() MapAny

Clone 克隆一个新的 Map

func (MapAny) Delete added in v0.1.7

func (m MapAny) Delete(key string) MapAny

Delete 删除指定 key

func (MapAny) Get added in v0.1.7

func (m MapAny) Get(key string, defaultValue ...any) any

Get 获取指定 key 的值,支持默认值

func (MapAny) GetBool added in v0.1.7

func (m MapAny) GetBool(key string, defaultValue ...bool) bool

GetBool 获取布尔值

func (MapAny) GetInt added in v0.1.7

func (m MapAny) GetInt(key string, defaultValue ...int) int

GetInt 获取整数值

func (MapAny) GetString added in v0.1.7

func (m MapAny) GetString(key string, defaultValue ...string) string

GetString 获取字符串值

func (MapAny) Has added in v0.1.7

func (m MapAny) Has(key string) bool

Has 检查 key 是否存在

func (MapAny) Keys added in v0.1.7

func (m MapAny) Keys() []string

Keys 获取所有 key

func (MapAny) Merge added in v0.1.7

func (m MapAny) Merge(other MapAny) MapAny

Merge 合并另一个 Map

func (*MapAny) Scan

func (m *MapAny) Scan(value interface{}) error

func (MapAny) Set added in v0.1.7

func (m MapAny) Set(key string, value any) MapAny

Set 设置值

func (MapAny) Value

func (m MapAny) Value() (driver.Value, error)

func (MapAny) Values added in v0.1.7

func (m MapAny) Values() []any

Values 获取所有 value

type MapString

type MapString map[string]string

MapString 字符串类型的 Map,支持数据库 JSON 序列化

func (MapString) Clone added in v0.1.7

func (m MapString) Clone() MapString

Clone 克隆一个新的 Map

func (MapString) Delete added in v0.1.7

func (m MapString) Delete(key string) MapString

Delete 删除指定 key

func (MapString) Get added in v0.1.7

func (m MapString) Get(key string, defaultValue ...string) string

Get 获取指定 key 的值,支持默认值

func (MapString) Has added in v0.1.7

func (m MapString) Has(key string) bool

Has 检查 key 是否存在

func (MapString) Keys added in v0.1.7

func (m MapString) Keys() []string

Keys 获取所有 key

func (MapString) Merge added in v0.1.7

func (m MapString) Merge(other MapString) MapString

Merge 合并另一个 Map

func (*MapString) Scan

func (m *MapString) Scan(value interface{}) error

func (MapString) Set added in v0.1.7

func (m MapString) Set(key, value string) MapString

Set 设置值

func (MapString) ToMapAny added in v0.1.7

func (m MapString) ToMapAny() MapAny

ToMapAny 转换为 MapAny

func (MapString) Value

func (m MapString) Value() (driver.Value, error)

func (MapString) Values added in v0.1.7

func (m MapString) Values() []string

Values 获取所有 value

type Slice added in v0.1.7

type Slice[T any] []T

泛型切片类型

func Map added in v0.1.7

func Map[T any, R any](s Slice[T], fn func(T) R) Slice[R]

Map 映射转换

func (*Slice[T]) Append added in v0.1.7

func (s *Slice[T]) Append(items ...T) Slice[T]

Append 追加元素

func (Slice[T]) Clone added in v0.1.7

func (s Slice[T]) Clone() Slice[T]

Clone 克隆切片

func (Slice[T]) Filter added in v0.1.7

func (s Slice[T]) Filter(fn func(T) bool) Slice[T]

Filter 过滤元素

func (Slice[T]) Len added in v0.1.7

func (s Slice[T]) Len() int

Len 获取长度

func (*Slice[T]) Scan added in v0.1.7

func (s *Slice[T]) Scan(value interface{}) error

func (Slice[T]) Value added in v0.1.7

func (s Slice[T]) Value() (driver.Value, error)

type StringSlice

type StringSlice []string

StringSlice 字符串切片,支持数据库 JSON 序列化

func (*StringSlice) Append added in v0.1.7

func (s *StringSlice) Append(items ...string) StringSlice

Append 追加元素

func (StringSlice) Clone added in v0.1.7

func (s StringSlice) Clone() StringSlice

Clone 克隆一个新的切片

func (StringSlice) Contains added in v0.1.7

func (s StringSlice) Contains(item string) bool

Contains 检查是否包含指定元素

func (StringSlice) Filter added in v0.1.7

func (s StringSlice) Filter(fn func(string) bool) StringSlice

Filter 过滤元素

func (StringSlice) IndexOf added in v0.1.7

func (s StringSlice) IndexOf(item string) int

IndexOf 查找元素索引,未找到返回 -1

func (StringSlice) Join added in v0.1.7

func (s StringSlice) Join(sep string) string

Join 连接为字符串

func (StringSlice) Map added in v0.1.7

func (s StringSlice) Map(fn func(string) string) StringSlice

Map 映射转换

func (*StringSlice) Remove added in v0.1.7

func (s *StringSlice) Remove(item string) StringSlice

Remove 移除指定元素(第一个匹配的)

func (*StringSlice) RemoveAt added in v0.1.7

func (s *StringSlice) RemoveAt(index int) StringSlice

RemoveAt 移除指定索引的元素

func (*StringSlice) Scan

func (s *StringSlice) Scan(value interface{}) error

func (StringSlice) Unique added in v0.1.7

func (s StringSlice) Unique() StringSlice

Unique 去重

func (StringSlice) Value

func (s StringSlice) Value() (driver.Value, error)

Directories

Path Synopsis
* @Author: kamalyes 501893067@qq.com * @Date: 2025-11-23 00:00:00 * @LastEditors: kamalyes 501893067@qq.com * @LastEditTime: 2025-11-26 21:55:50 * @FilePath: \go-sqlbuilder\constants\operators.go * @Description: 操作符常量定义 * * Copyright (c) 2025 by kamalyes, All Rights Reserved.
* @Author: kamalyes 501893067@qq.com * @Date: 2025-11-23 00:00:00 * @LastEditors: kamalyes 501893067@qq.com * @LastEditTime: 2025-11-26 21:55:50 * @FilePath: \go-sqlbuilder\constants\operators.go * @Description: 操作符常量定义 * * Copyright (c) 2025 by kamalyes, All Rights Reserved.
* @Author: kamalyes 501893067@qq.com * @Date: 2025-11-11 00:00:00 * @LastEditors: kamalyes 501893067@qq.com * @LastEditTime: 2025-11-23 13:05:48 * @FilePath: \go-sqlbuilder\db\handler.go * @Description: 数据库处理器 - Handler 接口和 GORM 实现 * * Copyright (c) 2025 by kamalyes, All Rights Reserved.
* @Author: kamalyes 501893067@qq.com * @Date: 2025-11-11 00:00:00 * @LastEditors: kamalyes 501893067@qq.com * @LastEditTime: 2025-11-23 13:05:48 * @FilePath: \go-sqlbuilder\db\handler.go * @Description: 数据库处理器 - Handler 接口和 GORM 实现 * * Copyright (c) 2025 by kamalyes, All Rights Reserved.
* @Author: kamalyes 501893067@qq.com * @Date: 2025-11-11 21:13:15 * @LastEditors: kamalyes 501893067@qq.com * @LastEditTime: 2025-11-28 13:15:15 * @FilePath: \go-sqlbuilder\repository\base.go * @Description: * * Copyright (c) 2025 by kamalyes, All Rights Reserved.
* @Author: kamalyes 501893067@qq.com * @Date: 2025-11-11 21:13:15 * @LastEditors: kamalyes 501893067@qq.com * @LastEditTime: 2025-11-28 13:15:15 * @FilePath: \go-sqlbuilder\repository\base.go * @Description: * * Copyright (c) 2025 by kamalyes, All Rights Reserved.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL