# ixDb **Repository Path**: ixgo/db ## Basic Information - **Project Name**: ixDb - **Description**: golang数据库帮助类 - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-09-19 - **Last Updated**: 2026-03-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ixOrm - 基于GORM的简化ORM帮助类 [![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.16-blue.svg)](https://golang.org/) [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) ixOrm 是一个基于 GORM 的简化 ORM 帮助类,专注于简单易用的API设计,支持多实例管理、智能缓存系统、链式操作和智能错误处理。 ## ✨ 特性 - 🚀 **简单易用**: 简洁的API设计,专注于表名操作 - 🏢 **多实例管理**: 支持多数据库实例管理,便于微服务架构 - 💾 **智能缓存系统**: - 支持Redis缓存和内存缓存 - 可同时配置两种缓存,默认使用Redis - 智能降级:Redis不可用时自动使用内存缓存 - 动态缓存类型选择 - 🔗 **链式操作**: 支持流畅的链式查询操作 - 🔍 **强大的查询构建器**: - ✅ 修复了 `!=`、`>=`、`<=` 等操作符的 BUG - 🆕 支持 LIKE 模糊查询 - 🆕 支持 OR 条件查询 - 🆕 支持 NULL 判断查询(IS NULL / IS NOT NULL) - 🆕 支持 BETWEEN 范围查询 - 🆕 支持原始 SQL 查询 - 🆕 提供 `Pluck`, `Increment`, `Decrement`, `FindByID`, `FirstOrCreate`, `Scopes` 等高级查改快捷语法糖 - ⚡️ **全局快捷操作**: 支持 `ixOrm.Table`, `ixOrm.DB`, `ixOrm.Transaction` 等包级别的无缝接入,摆脱强依赖 Client 实例的限制 - 🛡️ **安全事务封装**: 提供基于闭包的易用事务功能 `Transaction`,支持自动 Rollback/Commit 并在内部拦截恢复 Panic - 🛠 **自动建表**: 插入数据时自动检测并创建表 - 📊 **智能错误处理**: 表不存在时返回空数据而不是错误,防止程序崩溃 - 🔧 **高度可配置**: 支持字符集、GORM配置、连接字符串等完全自定义 - 🎯 **MySQL优化**: 专门优化支持MySQL数据库 - 🛡️ **安全稳定**: 完整的空值检查,防止程序崩溃 ## 📁 项目结构 ``` ixOrm/ ├── index.go # 包声明和说明 ├── types.go # 类型定义 ├── config.go # 配置管理 ├── cache.go # 缓存功能 ├── manager.go # 多实例管理 ├── client.go # 数据库客户端 ├── crud.go # CRUD操作 ├── query.go # 查询构建器 ├── utils.go # 工具方法 ├── tests/ # 测试文件 │ ├── config_test.go │ ├── manager_test.go │ ├── cache_test.go │ ├── charset_test.go │ ├── sqlconn_test.go │ ├── gorm_config_test.go │ └── integration_test.go └── README.md # 项目文档 ``` ## 🚀 快速开始 ### 安装依赖 ```bash go get gitee.com/ixgo/db go get gorm.io/gorm go get gorm.io/driver/mysql ``` ### 基本使用 ```go package main import ( "log" "time" ixOrm "gitee.com/ixgo/db" ) // 定义模型(可选,用于自动建表) type User struct { ID uint `gorm:"primaryKey" json:"id"` Name string `gorm:"size:100" json:"name"` Email string `gorm:"size:100;uniqueIndex" json:"email"` Age int `json:"age"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } func (User) TableName() string { return "users" } func main() { // 创建配置 config := ixOrm.DefaultConfig() config.Host = "localhost" config.Port = 3306 config.Username = "root" config.Password = "password" config.Database = "test_db" // 创建客户端 client, err := ixOrm.NewClient(config) if err != nil { log.Fatal(err) } defer client.Close() // 指定表名进行操作 userTable := client.Table("users") // 创建用户(自动建表) user := &User{ Name: "张三", Email: "zhangsan@example.com", Age: 25, } err = userTable.Create(user) if err != nil { log.Fatal(err) } log.Printf("创建用户成功,ID: %d", user.ID) // 链式查询(支持丰富的查询条件) var users []User err = userTable.Query(). Where("age >=", 18). // 比较查询(已修复 >=, <=, != 等操作符) WhereLike("name", "%张%"). // LIKE 模糊查询 🆕 WhereNotNull("email"). // NULL 判断查询 🆕 OrderBy("created_at"). Limit(10). Find(&users) if err != nil { log.Fatal(err) } log.Printf("查找到 %d 个用户", len(users)) // OR 条件查询 🆕 var vipUsers []User err = userTable.Query(). Where("status", "active"). OrWhere("vip_level", 5). // OR 条件支持 Find(&vipUsers) if err != nil { log.Fatal(err) } log.Printf("找到 %d 个 VIP 用户", len(vipUsers)) // 使用缓存查询(如果配置了缓存) var cachedUsers []User err = userTable.Query(). Where("status", "active"). WithCache(true). // 启用缓存 Find(&cachedUsers) if err != nil { log.Fatal(err) } log.Printf("缓存查询到 %d 个活跃用户", len(cachedUsers)) } ``` ### 智能缓存系统示例 ```go package main import ( "log" "time" ixOrm "gitee.com/ixgo/db" ) func main() { // 示例1: 同时配置Redis和内存缓存(推荐) client, err := ixOrm.NewClient( ixOrm.WithHost("localhost"), ixOrm.WithPort(3306), ixOrm.WithAuth("root", "password"), ixOrm.WithDatabase("test_db"), ixOrm.WithBothCaches([]interface{}{"localhost", 6379, "", 0}, time.Minute*10), ) if err != nil { log.Fatal(err) } defer client.Close() // 检查缓存状态 log.Printf("Redis缓存可用: %v", client.HasRedisCache()) log.Printf("内存缓存可用: %v", client.HasMemoryCache()) userTable := client.Table("users") // 示例2: 动态选择缓存类型 // 重要数据使用Redis缓存 var adminUsers []User err = userTable.Query(). Where("role", "admin"). WithCache(true). WithCacheType(ixOrm.CacheTypeRedis). // 使用Redis缓存 Find(&adminUsers) // 热点数据使用内存缓存 var activeUsers []User err = userTable.Query(). Where("status", "active"). WithCache(true). WithCacheType(ixOrm.CacheTypeMemory). // 使用内存缓存 Find(&activeUsers) // 示例3: 性能对比测试 start := time.Now() err = userTable.Query(). Where("department", "IT"). WithCache(true). Find(&activeUsers) firstQueryTime := time.Since(start) start = time.Now() err = userTable.Query(). Where("department", "IT"). WithCache(true). Find(&activeUsers) secondQueryTime := time.Since(start) log.Printf("第一次查询耗时: %v", firstQueryTime) log.Printf("第二次查询耗时: %v", secondQueryTime) log.Printf("缓存提升性能: %.2fx", float64(firstQueryTime)/float64(secondQueryTime)) } ``` ## 📚 详细使用指南 ### 配置管理 #### 基础配置 ```go // 使用默认配置 config := ixOrm.DefaultConfig() // 自定义配置 config := &ixOrm.Config{ // 方式一:使用完整连接字符串(优先级最高) SqlConn: "root:password@tcp(localhost:3306)/test_db?charset=utf8mb4&parseTime=True&loc=Local", // 方式二:使用分离的参数配置(SqlConn为空时使用) Host: "localhost", Port: 3306, Username: "root", Password: "password", Database: "test_db", // 连接参数配置 Charset: "utf8mb4", // 字符集 Collation: "utf8mb4_unicode_ci", // 排序规则 ParseTime: true, // 是否解析时间 Loc: "Local", // 时区 // 连接池配置 MaxOpenConns: 100, MaxIdleConns: 10, ConnMaxLifetime: time.Hour, // GORM配置 SlowThreshold: time.Millisecond * 200, LogLevel: ixOrm.LogLevelInfo, GormConfig: nil, // 自定义GORM配置 // 缓存配置(可选) EnableCache: false, CacheType: ixOrm.CacheTypeRedis, // 缓存类型:Redis(0), Memory(1), None(2) CacheTTL: time.Minute * 5, RedisConfig: &ixOrm.RedisConfig{ Host: "localhost", Port: 6379, Password: "", Database: 0, }, } ``` #### 使用配置选项函数 ```go config := ixOrm.DefaultConfig() // 方式一:使用完整连接字符串 + 智能缓存系统(推荐) client, err := ixOrm.NewClient(config, ixOrm.WithSqlConn("admin:secret@tcp(192.168.1.100:3307)/production?charset=utf8mb4&parseTime=true&loc=UTC"), ixOrm.WithConnectionPool(200, 20, time.Hour*2), ixOrm.WithBothCaches([]interface{}{"localhost", 6379, "", 0}, time.Minute*10), // 同时配置Redis和内存缓存 ixOrm.WithLogLevel(ixOrm.LogLevelWarn), ) // 方式二:使用分离参数配置 + Redis缓存 client, err := ixOrm.NewClient(config, ixOrm.WithHost("192.168.1.100"), ixOrm.WithPort(3307), ixOrm.WithAuth("admin", "secret"), ixOrm.WithDatabase("production"), ixOrm.WithCharsetAndCollation("utf8mb4", "utf8mb4_unicode_ci"), ixOrm.WithParseTime(true), ixOrm.WithLoc("UTC"), ixOrm.WithConnectionPool(200, 20, time.Hour*2), ixOrm.WithCache("localhost", 6379, "", 0, time.Minute*10), // 仅Redis缓存 ixOrm.WithLogLevel(ixOrm.LogLevelWarn), ) // 方式三:使用分离参数配置 + 内存缓存 client, err := ixOrm.NewClient(config, ixOrm.WithHost("192.168.1.100"), ixOrm.WithPort(3307), ixOrm.WithAuth("admin", "secret"), ixOrm.WithDatabase("production"), ixOrm.WithCharsetAndCollation("utf8mb4", "utf8mb4_unicode_ci"), ixOrm.WithParseTime(true), ixOrm.WithLoc("UTC"), ixOrm.WithConnectionPool(200, 20, time.Hour*2), ixOrm.WithMemoryCache(time.Minute*10), // 仅内存缓存 ixOrm.WithLogLevel(ixOrm.LogLevelWarn), ) // 方式四:分别配置两种缓存 client, err := ixOrm.NewClient(config, ixOrm.WithHost("192.168.1.100"), ixOrm.WithPort(3307), ixOrm.WithAuth("admin", "secret"), ixOrm.WithDatabase("production"), ixOrm.WithConnectionPool(200, 20, time.Hour*2), ixOrm.WithCache("localhost", 6379, "", 0, time.Minute*10), // 配置Redis ixOrm.WithMemoryCache(time.Minute*5), // 配置内存缓存 ixOrm.WithLogLevel(ixOrm.LogLevelWarn), ) ``` **配置参数说明:** - `SqlConn`: 完整的数据库连接字符串(优先级最高) - `Host`: 数据库主机地址 - `Port`: 数据库端口号 - `Username`: 数据库用户名 - `Password`: 数据库密码 - `Database`: 数据库名称 - `Charset`: 字符集,默认 utf8mb4(支持完整Unicode,包括emoji) - `Collation`: 排序规则,默认 utf8mb4_unicode_ci(Unicode标准排序) - `ParseTime`: 是否解析时间类型,默认 true - `Loc`: 时区设置,默认 Local(本地时区) - `MaxOpenConns`: 最大打开连接数 - `MaxIdleConns`: 最大空闲连接数 - `ConnMaxLifetime`: 连接最大生存时间 - `SlowThreshold`: 慢查询阈值 - `LogLevel`: 日志级别 (Silent=1, Error=2, Warn=3, Info=4) - `GormConfig`: 自定义GORM配置(优先级最高) - `EnableCache`: 是否启用缓存 - `CacheType`: 缓存类型 (Redis=0, Memory=1, None=2),默认Redis - `CacheTTL`: 缓存过期时间 #### 连接字符串配置 支持直接使用完整的数据库连接字符串,提供最大的灵活性: ```go // 基本连接 config.SqlConn = "root:password@tcp(localhost:3306)/testdb" // 带字符集 config.SqlConn = "user:pass@tcp(localhost:3306)/mydb?charset=utf8mb4" // 完整参数 config.SqlConn = "admin:secret@tcp(db.example.com:3306)/proddb?charset=utf8mb4&collation=utf8mb4_unicode_ci&parseTime=true&loc=UTC&timeout=30s" // SSL连接 config.SqlConn = "user:pass@tcp(secure.db.com:3306)/mydb?charset=utf8mb4&tls=true" // Unix套接字 config.SqlConn = "user:pass@unix(/var/run/mysqld/mysqld.sock)/mydb?charset=utf8mb4" // 使用配置选项函数 client, err := ixOrm.NewClient(config, ixOrm.WithSqlConn("root:password@tcp(localhost:3306)/testdb?charset=utf8mb4"), ) ``` #### 字符集配置 ixOrm 支持灵活的字符集配置,默认使用 `utf8mb4` 字符集以支持完整的 Unicode 字符(包括 emoji)。 ```go // 使用默认字符集(utf8mb4 + utf8mb4_unicode_ci) config := ixOrm.DefaultConfig() // 自定义字符集 client, err := ixOrm.NewClient(config, ixOrm.WithCharset("utf8mb4"), // 设置字符集 ixOrm.WithCollation("utf8mb4_unicode_ci"), // 设置排序规则 ixOrm.WithCharsetAndCollation("utf8", "utf8_general_ci"), // 同时设置 ixOrm.WithParseTime(true), // 启用时间解析 ixOrm.WithLoc("UTC"), // 设置时区 ) ``` **常用字符集配置:** ```go // UTF8MB4 - 推荐(支持emoji等4字节Unicode字符) ixOrm.WithCharsetAndCollation("utf8mb4", "utf8mb4_unicode_ci") // UTF8 - 兼容性好(仅支持3字节Unicode字符) ixOrm.WithCharsetAndCollation("utf8", "utf8_unicode_ci") // 中文应用 ixOrm.WithCharsetAndCollation("utf8mb4", "utf8mb4_unicode_ci") // 性能优先(排序速度更快) ixOrm.WithCharsetAndCollation("utf8mb4", "utf8mb4_general_ci") // 其他字符集 ixOrm.WithCharsetAndCollation("latin1", "latin1_swedish_ci") // 西欧语言 ixOrm.WithCharsetAndCollation("gbk", "gbk_chinese_ci") // 中文GBK ``` #### GORM 配置 ixOrm 支持完全自定义的 GORM 配置,提供了两种配置方式: ##### 1. 使用完整的 GORM 配置 ```go // 创建自定义 GORM 配置 gormConfig := &gorm.Config{ DryRun: false, PrepareStmt: true, Logger: logger.New( log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ SlowThreshold: time.Millisecond * 100, LogLevel: logger.Info, IgnoreRecordNotFoundError: true, Colorful: true, }, ), DisableAutomaticPing: false, AllowGlobalUpdate: false, CreateBatchSize: 1000, } // 使用自定义 GORM 配置 client, err := ixOrm.NewClient(config, ixOrm.WithGormConfig(gormConfig), ) ``` ##### 2. 使用配置选项函数 ```go // 使用配置选项函数逐项设置 client, err := ixOrm.NewClient(config, // GORM 基础配置 ixOrm.WithGormDryRun(false), ixOrm.WithGormPrepareStmt(true), ixOrm.WithGormDisableAutomaticPing(false), // 日志配置 ixOrm.WithGormLogger(ixOrm.NewDefaultGormLogger(logger.Info, time.Millisecond*100)), // 更新和查询配置 ixOrm.WithGormAllowGlobalUpdate(false), ixOrm.WithGormQueryFields(true), ixOrm.WithGormCreateBatchSize(1000), // 迁移配置 ixOrm.WithGormDisableForeignKeyConstraintWhenMigrating(true), ixOrm.WithGormIgnoreRelationshipsWhenMigrating(false), // 事务配置 ixOrm.WithGormDisableNestedTransaction(false), ) ``` ##### 3. 日志器配置 ```go // 使用默认日志器 defaultLogger := ixOrm.NewDefaultGormLogger(logger.Info, time.Millisecond*200) // 使用静默日志器 silentLogger := ixOrm.NewSilentGormLogger() // 应用日志器 client, err := ixOrm.NewClient(config, ixOrm.WithGormLogger(defaultLogger), ) ``` ### 多实例管理 #### 添加和管理实例 ```go // 添加默认实例 config := ixOrm.DefaultConfig() err := ixOrm.AddDefault(config) // 添加命名实例 userDBConfig := &ixOrm.Config{...} orderDBConfig := &ixOrm.Config{...} err = ixOrm.Add("user_db", userDBConfig) err = ixOrm.Add("order_db", orderDBConfig) // 获取实例 userDB, err := ixOrm.Get("user_db") orderDB, err := ixOrm.Get("order_db") defaultDB, err := ixOrm.GetDefault() // 列出所有实例 instances := ixOrm.List() fmt.Println("实例列表:", instances) // 健康检查 healthResults := ixOrm.HealthCheck() for name, err := range healthResults { if err != nil { fmt.Printf("实例 %s 不健康: %v\n", name, err) } } // 关闭所有实例 err = ixOrm.CloseAll() ``` ### 表操作 #### 指定表名操作 ```go client, _ := ixOrm.NewClient(config) // 指定表名 // 方式二:使用全局快捷函数(推荐,如果只有单个主数据库默认走 default 实例) ixOrm.Table("users").Find(&users) // 多库时指定实例: ixOrm.Table("admin_logs", "log_db").Create(&log) ``` #### 事务控制 (Transaction) 🆕 ```go // 简单的闭包安全事务机制,当函数返回 error 时自动隐式回滚 err := ixOrm.Transaction(func(tx *ixOrm.Client) error { // 这里的 tx 拥有与外层一样的 Cache 配置,但绑定了内部事务 DB if err := tx.Table("accounts").Where("id", 1).Decrement("balance", 100); err != nil { return err // 遇到故障自动 Rollback } if err := tx.Table("accounts").Where("id", 2).Increment("balance", 100); err != nil { return err } // 返回 nil 自动 Commit,且内部自带 Panic 恢复保护 return nil }) ``` ### CRUD 操作 #### 创建记录 ```go userTable := client.Table("users") // 创建单个记录(自动建表) user := map[string]interface{}{ "name": "张三", "email": "zhangsan@example.com", "age": 25, } err := userTable.Create(user) if err != nil { log.Fatal(err) } // 使用结构体创建 type User struct { Name string `json:"name"` Email string `json:"email"` Age int `json:"age"` } user := &User{Name: "李四", Email: "lisi@example.com", Age: 30} err = userTable.Create(user) // 批量创建 users := []map[string]interface{}{ {"name": "用户1", "email": "user1@example.com", "age": 20}, {"name": "用户2", "email": "user2@example.com", "age": 22}, } err = userTable.CreateInBatches(users, 100) // 每批100条 // 创建选项 options := &ixOrm.CreateOptions{ AutoMigrate: true, // 是否自动建表(默认true) } err = userTable.Create(user, options) ``` **特殊行为:** - 当表不存在时,Create操作会自动创建表(如果 AutoMigrate 为 true) - 创建失败时会自动重试一次(在自动建表后) #### 查询记录 ```go userTable := client.Table("users") // 查找所有记录 var users []map[string]interface{} err := userTable.Find(&users) // 使用结构体接收 var userList []User err = userTable.Find(&userList) // 查找单条记录 var user User err = userTable.Where("email", "zhangsan@example.com").FindOne(&user) if err == gorm.ErrRecordNotFound { fmt.Println("用户不存在") } else if err != nil { log.Fatal(err) } // 复杂查询条件 var adults []User err = userTable.Query(). Where("age > ?", 18). Where("status", "active"). OrderBy("created_at"). Limit(10). Find(&adults) // 使用 QueryOptions options := &ixOrm.QueryOptions{ Conditions: map[string]interface{}{ "age >": 18, "status": "active", "name LIKE": "%张%", }, OrderBy: []string{"created_at DESC"}, Limit: 10, Offset: 0, Select: []string{"id", "name", "email"}, } err = userTable.Find(&users, options) // 计数查询 count, err := userTable.Count() fmt.Printf("总用户数: %d\n", count) // 带条件计数 count, err = userTable.Where("age > ?", 18).Count() // 检查记录是否存在 exists, err := userTable.Where("email", "test@example.com").Exists() ``` **查询条件支持:** ixOrm 支持丰富的查询条件,包括等值查询、比较操作、模糊查询、范围查询、OR条件等。 ##### 1. 基础查询条件 ```go // 等于 Where("id", 1) // WHERE id = ? Where("name", "张三") // WHERE name = ? // 比较操作(已修复 !=, >=, <= 等操作符的 BUG) Where("age >", 18) // WHERE age > ? Where("age <", 60) // WHERE age < ? Where("age >=", 18) // WHERE age >= ? ✅ 已修复 Where("age <=", 60) // WHERE age <= ? ✅ 已修复 Where("age !=", 0) // WHERE age != ? ✅ 已修复 Where("age <>", 0) // WHERE age <> ? ✅ 已修复 // IN 查询 WhereIn("status", []interface{}{"active", "pending"}) // WHERE status IN ('active', 'pending') WhereIn("id", []interface{}{1, 2, 3, 4, 5}) // WHERE id IN (1, 2, 3, 4, 5) ``` ##### 2. LIKE 模糊查询 🆕 ```go // TableOperator 方式 userTable.WhereLike("name", "%张%").Find(&users) // WHERE name LIKE '%张%' // QueryBuilder 方式 userTable.Query(). Where("age >", 18). WhereLike("name", "%张%"). Find(&users) // WHERE age > 18 AND name LIKE '%张%' // 多个 LIKE 条件 userTable.Query(). WhereLike("name", "%张%"). WhereLike("email", "%@example.com"). Find(&users) // WHERE name LIKE '%张%' AND email LIKE '%@example.com' ``` ##### 3. NULL 判断查询 🆕 ```go // IS NULL userTable.WhereNull("deleted_at").Find(&users) // WHERE deleted_at IS NULL // IS NOT NULL userTable.WhereNotNull("email").Find(&users) // WHERE email IS NOT NULL // 组合使用 userTable.Query(). Where("status", "active"). WhereNotNull("email"). WhereNull("deleted_at"). Find(&users) // WHERE status = 'active' AND email IS NOT NULL AND deleted_at IS NULL ``` ##### 4. BETWEEN 范围查询 🆕 ```go // BETWEEN userTable.WhereBetween("age", 18, 60).Find(&users) // WHERE age BETWEEN 18 AND 60 // NOT BETWEEN userTable.Query(). WhereNotBetween("age", 18, 25). Find(&users) // WHERE age NOT BETWEEN 18 AND 25 // 日期范围查询 startDate := time.Now().AddDate(0, -1, 0) // 一个月前 endDate := time.Now() userTable.WhereBetween("created_at", startDate, endDate).Find(&users) // WHERE created_at BETWEEN ? AND ? ``` ##### 5. 原始 SQL 查询 🆕 ```go // 简单原始 SQL userTable.WhereRaw("YEAR(created_at) = ?", 2024).Find(&users) // WHERE YEAR(created_at) = 2024 // 复杂 SQL 表达式 userTable.Query(). Where("status", "active"). WhereRaw("(score > ? OR level > ?)", 90, 5). Find(&users) // WHERE status = 'active' AND (score > 90 OR level > 5) // 子查询 userTable.WhereRaw("id IN (SELECT user_id FROM orders WHERE total > ?)", 1000).Find(&users) // WHERE id IN (SELECT user_id FROM orders WHERE total > 1000) // 多个原始 SQL 条件 userTable.Query(). Where("status", "active"). WhereRaw("YEAR(created_at) = ?", 2024). WhereRaw("MONTH(created_at) > ?", 6). Find(&users) // WHERE status = 'active' AND YEAR(created_at) = 2024 AND MONTH(created_at) > 6 ``` ##### 6. OR 条件查询 🆕 ```go // 简单 OR 条件 userTable.Query(). Where("status", "active"). OrWhere("vip_level", 5). Find(&users) // WHERE status = 'active' OR vip_level = 5 // OR IN userTable.Query(). Where("age >", 18). OrWhereIn("city", []interface{}{"北京", "上海", "深圳"}). Find(&users) // WHERE age > 18 OR city IN ('北京', '上海', '深圳') // OR LIKE userTable.Query(). WhereLike("name", "%张%"). OrWhereLike("name", "%李%"). Find(&users) // WHERE name LIKE '%张%' OR name LIKE '%李%' // OR NULL userTable.Query(). Where("status", "inactive"). OrWhereNull("last_login_at"). Find(&users) // WHERE status = 'inactive' OR last_login_at IS NULL // OR NOT NULL userTable.Query(). Where("age <", 18). OrWhereNotNull("parent_id"). Find(&users) // WHERE age < 18 OR parent_id IS NOT NULL // OR BETWEEN userTable.Query(). WhereBetween("age", 18, 25). OrWhereBetween("age", 60, 100). Find(&users) // WHERE age BETWEEN 18 AND 25 OR age BETWEEN 60 AND 100 // 复杂 OR 条件组合 userTable.Query(). Where("status", "active"). // AND status = 'active' Where("age >", 18). // AND age > 18 OrWhere("vip_level", 10). // OR vip_level = 10 OrWhereIn("city", []interface{}{"北京", "上海"}). // OR city IN (...) Find(&users) // WHERE status = 'active' AND age > 18 OR vip_level = 10 OR city IN ('北京', '上海') ``` ##### 7. 复杂查询组合 ```go // 组合多种查询条件 userTable.Query(). Where("status", "active"). // AND status = 'active' Where("age >", 18). // AND age > 18 Where("age <=", 60). // AND age <= 60 WhereLike("name", "%张%"). // AND name LIKE '%张%' WhereNotNull("email"). // AND email IS NOT NULL WhereBetween("score", 60, 100). // AND score BETWEEN 60 AND 100 WhereRaw("level > ?", 3). // AND level > 3 OrWhere("vip_level", 10). // OR vip_level = 10 OrderByDesc("created_at"). Limit(20). Find(&users) // 使用 map 条件(仍然支持) options := &ixOrm.QueryOptions{ Conditions: map[string]interface{}{ "status": "active", "age >": 18, "name LIKE": "%张%", }, } userTable.Find(&users, options) ``` **特殊行为:** - 当表不存在时,查询操作返回空结果而不是错误 - 这样设计是为了避免在动态表场景下的错误处理复杂性 #### 更新记录 ```go userTable := client.Table("users") // 更新记录 updates := map[string]interface{}{ "age": 26, "updated_at": time.Now(), } err := userTable.Where("email", "zhangsan@example.com").Update(updates) // 批量更新 err = userTable.Where("status", "inactive").Update(map[string]interface{}{ "status": "active", }) // 复杂条件更新 err = userTable.Query(). Where("age > ?", 60). Where("status", "active"). Update(map[string]interface{}{"status": "senior"}) // 更新选项 options := &ixOrm.UpdateOptions{ Conditions: map[string]interface{}{ "age >": 18, }, ClearCache: true, // 更新后清除缓存 } err = userTable.Update(updates, options) ``` #### 删除记录 ```go userTable := client.Table("users") // 软删除(默认) err := userTable.Where("email", "zhangsan@example.com").Delete() // 硬删除 err = userTable.Where("email", "zhangsan@example.com").Delete(false) // 复杂条件删除 err = userTable.Query(). Where("age < ?", 18). Where("status", "inactive"). Delete() // 软删除 err = userTable.Query(). Where("created_at < ?", time.Now().AddDate(-1, 0, 0)). Delete(false) // 硬删除 // 删除选项 options := &ixOrm.DeleteOptions{ Conditions: map[string]interface{}{ "status": "inactive", "age <": 18, }, SoftDelete: true, // 是否软删除 ClearCache: true, // 删除后清除缓存 } err = userTable.Delete(options) ``` #### 插入或更新记录(Upsert) ```go userTable := client.Table("users") // 方式一:单参数模式(推荐) // 使用 GORM 的 Save 方法,自动判断插入或更新 user := &User{ ID: 1, // 如果ID=1存在则更新,不存在则插入 Name: "张三", Email: "zhangsan@example.com", Age: 25, } err := userTable.Upsert(user) if err != nil { log.Fatal(err) } // 方式二:双参数模式 // 分别指定插入和更新的数据 insertData := &User{ Name: "张三", Email: "zhangsan@example.com", Age: 25, } updateData := map[string]interface{}{ "name": "张三(已更新)", "age": 26, "updated_at": time.Now(), } err = userTable.Upsert(insertData, updateData) if err != nil { log.Fatal(err) } // 批量 Upsert users := []User{ {ID: 1, Name: "用户1", Email: "user1@example.com"}, {ID: 2, Name: "用户2", Email: "user2@example.com"}, {ID: 3, Name: "用户3", Email: "user3@example.com"}, } for _, user := range users { err := userTable.Upsert(&user) if err != nil { log.Printf("Upsert 用户 %d 失败: %v", user.ID, err) } } // 使用 map 数据 userData := map[string]interface{}{ "id": 1, "name": "李四", "email": "lisi@example.com", "age": 30, } err = userTable.Upsert(userData) ``` #### 分批处理游标 (Chunk) 🆕 在大表遍历场景下(如几百万用户的标签清洗处理),普通的 `Find` 查询极易导致程序 OOM(内存溢出)。你可以使用 `Chunk` 函数进行安全可靠的按需防爆内存遍历: ```go var users []User // 每次固定仅从 DB 提取 100 条并推入闭包中消费,防止一次性拉起数万结构体 err := ixOrm.Table("users").Where("status", "active").Chunk(&users, 100, func(tx *gorm.DB, batch int) error { log.Printf("正在处理第 %d 批数据...", batch) for _, u := range users { // ... 业务处理 ... } // 返回 nil 继续拉取下一批次;返回返回任何 error 即可随时强制中止提取 return nil }) ``` **Upsert 工作原理:** **单参数模式:** - 使用 GORM 的 `Save` 方法 - 如果模型有主键值且记录存在,则更新全部字段 - 如果主键值为零值或记录不存在,则插入新记录 **双参数模式:** 1. 先尝试用第一个参数插入(`Create`) 2. 如果插入成功,操作完成 3. 如果是主键冲突错误,提取主键条件,用第二个参数更新 4. 如果是其他错误,直接返回错误 **特殊行为:** - 自动建表:表不存在时自动创建表 - 主键识别:自动识别 `gorm:"primaryKey"` 标签或 `ID` 字段 - 不自动清缓存:操作完成后不会自动清除缓存,避免影响其他缓存 **使用场景:** - 数据同步:从外部系统同步数据 - 批量导入:批量导入可能重复的数据 - 配置更新:更新可能不存在的配置项 - 用户信息:更新用户资料(存在则更新,不存在则创建) ### 链式查询操作 #### 基础链式查询 ```go userTable := client.Table("users") // 链式查询 var users []User err := userTable.Query(). Where("age > ?", 18). Where("status", "active"). OrderBy("created_at"). Limit(10). Find(&users) // 复杂查询 err = userTable.Query(). Where("age > ?", 18). WhereIn("city", []interface{}{"北京", "上海", "深圳"}). OrderByDesc("created_at"). Select("id", "name", "email"). Limit(20). Offset(10). Find(&users) ``` #### 查询构建器方法 ```go qb := userTable.Query() // AND 条件查询 qb.Where("name", "张三") // 等值查询 qb.Where("age >", 18) // 比较查询 qb.Where("age !=", 0) // 不等于查询 ✅ 已修复 qb.WhereIn("status", []interface{}{"active", "pending"}) // IN 查询 qb.WhereLike("name", "%张%") // LIKE 查询 🆕 qb.WhereNull("deleted_at") // IS NULL 查询 🆕 qb.WhereNotNull("email") // IS NOT NULL 查询 🆕 qb.WhereBetween("age", 18, 60) // BETWEEN 查询 🆕 qb.WhereNotBetween("score", 0, 59) // NOT BETWEEN 查询 🆕 qb.WhereRaw("YEAR(created_at) = ?", 2024) // 原始 SQL 查询 🆕 // OR 条件查询 🆕 qb.OrWhere("vip_level", 10) // OR 等值查询 qb.OrWhereIn("city", []interface{}{"北京", "上海"}) // OR IN 查询 qb.OrWhereLike("email", "%@vip.com") // OR LIKE 查询 qb.OrWhereNull("parent_id") // OR IS NULL 查询 qb.OrWhereNotNull("sponsor_id") // OR IS NOT NULL 查询 qb.OrWhereBetween("level", 5, 10) // OR BETWEEN 查询 // 排序 qb.OrderBy("created_at") // 升序 qb.OrderByDesc("updated_at") // 降序 // 分组 qb.GroupBy("department", "level") // 分页 qb.Limit(10) qb.Offset(20) qb.Page(3, 10) // 第3页,每页10条 // 字段选择 qb.Select("id", "name", "email") // 缓存控制 qb.WithCache(true) // 启用自动缓存键 qb.WithCache("custom_key", time.Minute*10) // 自定义缓存键和过期时间 qb.WithCacheType(ixOrm.CacheTypeRedis) // 指定缓存类型 // 上下文 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) defer cancel() qb.WithContext(ctx) // 执行查询 var users []User err := qb.Find(&users) // 查找单条 var user User err = qb.FindOne(&user) // 高级查改快捷方法 🆕 err = userTable.FindByID(1, &user) // 极速提取单条主键记录 err = userTable.FirstOrCreate(&user, map[string]interface{}{}) // 不存在即创建 err = qb.Pluck("name", &names) // 提取单列至切片中,避免结构体反射 err = qb.Increment("view_count", 1) // 字段安全的原子级自增 err = qb.Decrement("stock", 10) // 字段安全的原子级自减 err = qb.UpdateColumn("status", 1) // 字段静默更新(无视 Hook 和自动时间戳) err = qb.UpdateColumns(map[string]interface{}{"status": 1}) // 批量字段静默更新 qb.Scopes(ActiveOnly, PaginateStrategy) // 支持复用查询作用域 // 计数 count, err := qb.Count() // 检查存在 exists, err := qb.Exists() // 更新 err = qb.Update(map[string]interface{}{"status": "updated"}) // 删除 err = qb.Delete() // 软删除 err = qb.Delete(false) // 硬删除 ``` #### 分页查询 ```go userTable := client.Table("users") var users []User result, err := userTable.Query(). Where("status", "active"). OrderByDesc("created_at"). Paginate(1, 20, &users) // 第1页,每页20条 if err != nil { log.Fatal(err) } fmt.Printf("总记录数: %d\n", result.Total) fmt.Printf("当前页: %d/%d\n", result.Page, result.TotalPages) fmt.Printf("每页大小: %d\n", result.PageSize) fmt.Printf("数据: %+v\n", result.Data) ``` ### 智能缓存系统 ixOrm 提供了强大的智能缓存系统,支持Redis缓存、内存缓存以及同时使用两种缓存。 #### 缓存配置模式 ```go // 1. WithCache(true) - 启用自动缓存键生成 userTable.WithCache(true) // 自动生成键格式:ixorm:实例名:数据库名:表名:操作:参数 // 2. WithCache(false) - 禁用缓存 userTable.WithCache(false) // 3. WithCache("key") - 指定缓存键,使用默认过期时间 userTable.WithCache("my_users") // 4. WithCache("key", time.Minute*5) - 指定缓存键和过期时间 userTable.WithCache("my_users", time.Minute*10) // 5. WithCacheType(CacheType) - 指定缓存类型 userTable.WithCacheType(ixOrm.CacheTypeRedis) // 使用Redis缓存 userTable.WithCacheType(ixOrm.CacheTypeMemory) // 使用内存缓存 userTable.WithCacheType(ixOrm.CacheTypeNone) // 不使用缓存 ``` #### 启用Redis缓存(默认) ```go // 创建带Redis缓存的配置 config := ixOrm.DefaultConfig() ixOrm.WithCache("localhost", 6379, "", 0, time.Minute*10)(config) client, err := ixOrm.NewClient(config) if err != nil { log.Fatal(err) } // 使用自动缓存键 userTable := client.Table("users").WithCache(true) // 使用自定义缓存键 userTable := client.Table("users").WithCache("active_users", time.Minute*15) // 查询会自动使用缓存 var users []User err = userTable.Where("status", "active").Find(&users) ``` #### 启用内存缓存 ```go // 创建带内存缓存的配置 client, err := ixOrm.NewClient( ixOrm.WithHost("localhost"), ixOrm.WithPort(3306), ixOrm.WithAuth("root", "password"), ixOrm.WithDatabase("test_db"), ixOrm.WithMemoryCache(time.Minute*10), // 使用内存缓存,TTL为10分钟 ) // 使用内存缓存查询 userTable := client.Table("users").WithCache(true) var users []User err = userTable.Where("status", "active").Find(&users) ``` #### 同时使用Redis和内存缓存 ```go // 方式1: 使用WithBothCaches同时配置两种缓存 client, err := ixOrm.NewClient( ixOrm.WithHost("localhost"), ixOrm.WithPort(3306), ixOrm.WithAuth("root", "password"), ixOrm.WithDatabase("test_db"), ixOrm.WithBothCaches([]interface{}{"localhost", 6379, "", 0}, time.Minute*10), // 同时配置Redis和内存缓存 ) // 方式2: 分别配置Redis和内存缓存 client, err := ixOrm.NewClient( ixOrm.WithHost("localhost"), ixOrm.WithPort(3306), ixOrm.WithAuth("root", "password"), ixOrm.WithDatabase("test_db"), ixOrm.WithCache("localhost", 6379, "", 0), // 配置Redis缓存 ixOrm.WithMemoryCache(time.Minute*5), // 配置内存缓存 ) // 检查缓存可用性 fmt.Printf("Redis缓存可用: %v\n", client.HasRedisCache()) fmt.Printf("内存缓存可用: %v\n", client.HasMemoryCache()) fmt.Printf("默认缓存类型: %T\n", client.GetCache()) // 默认使用Redis ``` #### 动态选择缓存类型 ```go // 创建支持多种缓存类型的客户端 client, err := ixOrm.NewClient( ixOrm.WithHost("localhost"), ixOrm.WithPort(3306), ixOrm.WithAuth("root", "password"), ixOrm.WithDatabase("test_db"), ixOrm.WithCache("localhost", 6379, "", 0), // 配置Redis缓存 ixOrm.WithMemoryCache(time.Minute*5), // 配置内存缓存 ) // 在查询时动态选择缓存类型 table := client.Table("users") // 使用Redis缓存查询 var usersRedis []User err = table.Query(). Where("id", 1). WithCache(true). WithCacheType(ixOrm.CacheTypeRedis). Find(&usersRedis) // 使用内存缓存查询 var usersMemory []User err = table.Query(). Where("id", 2). WithCache(true). WithCacheType(ixOrm.CacheTypeMemory). Find(&usersMemory) // 使用QueryOptions指定缓存类型 options := &ixOrm.QueryOptions{ TableName: "users", Conditions: map[string]interface{}{ "status": "active", }, UseCache: true, CacheType: ixOrm.CacheTypeMemory, // 指定使用内存缓存 CacheTTL: time.Minute * 5, // 缓存5分钟 } var usersOptions []User err = table.Find(&usersOptions, options) ``` #### 缓存类型对比 | 特性 | Redis缓存 | 内存缓存 | 无缓存 | |------|-----------|----------|--------| | **性能** | 中等 | 极高 | 低 | | **持久化** | ✅ 支持 | ❌ 不支持 | ❌ 不支持 | | **分布式** | ✅ 支持 | ❌ 不支持 | ❌ 不支持 | | **内存占用** | 低 | 高 | 无 | | **网络依赖** | 是 | 否 | 否 | | **部署复杂度** | 中等 | 简单 | 简单 | | **适用场景** | 生产环境 | 开发/测试 | 实时数据 | #### 缓存类型选择指南 | 场景 | 推荐缓存类型 | 理由 | |------|-------------|------| | 🏭 **分布式微服务** | Redis缓存 | 数据共享,支持集群部署 | | 💻 **单机应用** | 内存缓存 | 性能更高,延迟更低 | | 🛠 **开发测试** | 内存缓存 | 无需Redis依赖,部署简单 | | ⚡ **高并发读取** | 内存缓存 | 减少网络开销,提升性能 | | 🔒 **数据一致性要求高** | Redis缓存 | 支持持久化和集群同步 | | 💾 **内存资源有限** | Redis缓存 | 避免占用应用内存 | | ⏰ **临时数据缓存** | 内存缓存 | 自动过期清理,无需持久化 | | 📊 **实时数据查询** | 无缓存 | 保证数据实时性 | #### 性能对比 ```go // 性能测试示例 func benchmarkCache() { // Redis缓存性能测试 start := time.Now() for i := 0; i < 1000; i++ { var users []User redisClient.Table("users").WithCache(true).Find(&users) } redisTime := time.Since(start) // 内存缓存性能测试 start = time.Now() for i := 0; i < 1000; i++ { var users []User memoryClient.Table("users").WithCache(true).Find(&users) } memoryTime := time.Since(start) fmt.Printf("Redis缓存耗时: %v\n", redisTime) fmt.Printf("内存缓存耗时: %v\n", memoryTime) fmt.Printf("内存缓存比Redis快: %.2fx\n", float64(redisTime)/float64(memoryTime)) } ``` #### 缓存操作与管理 ```go // 1. 获取缓存实例 // 获取默认缓存实例 cache := client.GetCache() // 获取指定类型的缓存实例 redisCache := client.GetCacheByType(ixOrm.CacheTypeRedis) memoryCache := client.GetCacheByType(ixOrm.CacheTypeMemory) // 直接获取特定缓存实例(如果同时配置了两种缓存) redisCache := client.GetRedisCache() memoryCache := client.GetMemoryCache() // 2. 缓存状态检查 fmt.Printf("Redis缓存可用: %v\n", client.HasRedisCache()) fmt.Printf("内存缓存可用: %v\n", client.HasMemoryCache()) fmt.Printf("默认缓存类型: %T\n", client.GetCache()) // 3. 手动缓存操作 err = cache.Set("custom_key", data, time.Minute*10) var result Data exists, err := cache.Get("custom_key", &result) // 删除特定缓存 err = cache.Del("key1", "key2") // 模式删除 err = cache.DelPattern("*users*") // 删除包含users的所有缓存 err = cache.DelPattern("ixorm:*") // 删除所有ixorm缓存 // 清空所有缓存 err = cache.Clear() // 4. 表级别的缓存操作 userTable.ClearCache() // 清除当前表的所有缓存 userTable.ClearAllCache() // 清除所有缓存 // 5. 动态切换默认缓存类型 client.SetDefaultCacheType(ixOrm.CacheTypeMemory) // 切换到内存缓存 client.SetDefaultCacheType(ixOrm.CacheTypeRedis) // 切换到Redis缓存 // 6. 分别清理不同缓存 if client.HasRedisCache() { client.GetRedisCache().Clear() } if client.HasMemoryCache() { client.GetMemoryCache().Clear() } ``` #### 缓存策略 ```go // 查询时启用自动缓存 var users []User err := userTable.Query(). Where("department", "IT"). WithCache(true). // 自动生成缓存键 Find(&users) // 查询时使用自定义缓存 err := userTable.Query(). Where("status", "active"). WithCache("active_users_v2", time.Hour). Find(&users) // 更新时自动清除缓存 err = userTable.Query(). Where("id", 1). Update(map[string]interface{}{"status": "updated"}) // 更新操作会自动清除相关缓存 // 手动清除缓存 userTable.ClearCache() // 清除当前表缓存 // 混合缓存策略示例 func mixedCacheStrategy() { client, _ := ixOrm.NewClient( ixOrm.WithHost("localhost"), ixOrm.WithPort(3306), ixOrm.WithAuth("root", "password"), ixOrm.WithDatabase("test_db"), ixOrm.WithCache("localhost", 6379, "", 0), // 配置Redis缓存 ) table := client.Table("users") // 频繁查询的数据使用内存缓存(性能更好) var hotUsers []User err := table.Query(). Where("status", "active"). WithCache(true). WithCacheType(ixOrm.CacheTypeMemory). // 使用内存缓存 Find(&hotUsers) // 重要数据使用Redis缓存(持久化) var importantUsers []User err = table.Query(). Where("role", "admin"). WithCache("admin_users", time.Hour*24). WithCacheType(ixOrm.CacheTypeRedis). // 使用Redis缓存 Find(&importantUsers) // 临时数据不使用缓存(直接查询) var tempUsers []User err = table.Query(). Where("created_at", ">", time.Now().Add(-time.Hour)). WithCacheType(ixOrm.CacheTypeNone). // 不使用缓存 Find(&tempUsers) // 动态切换默认缓存类型 fmt.Printf("切换前默认缓存: %T\n", client.GetCache()) client.SetDefaultCacheType(ixOrm.CacheTypeMemory) fmt.Printf("切换到内存缓存后: %T\n", client.GetCache()) client.SetDefaultCacheType(ixOrm.CacheTypeRedis) fmt.Printf("切换到Redis缓存后: %T\n", client.GetCache()) } ``` #### 缓存键生成规则 当使用 `WithCache(true)` 时,系统会自动生成缓存键: **Redis缓存键格式:** ``` 格式:ixorm:实例名:数据库名:表名:操作:参数 示例: - ixorm:user_db:production:users:find:age > ?_18_created_at_10 - ixorm:order_db:shop:orders:count:status_active - ixorm:default:test:products:findone:id_123 ``` **内存缓存键格式:** ``` 格式:ixorm:memory:数据库名:表名:操作:参数 示例: - ixorm:memory:test_db:users:find:status_active_limit_10 - ixorm:memory:test_db:orders:count:user_id_123 - ixorm:memory:test_db:products:findone:id_456 ``` **缓存键特点:** - Redis缓存键包含实例名,支持多实例环境 - 内存缓存键简化格式,提高内存使用效率 - 所有缓存键都包含数据库名和表名,避免冲突 - 操作类型和参数确保查询的唯一性 ### 上下文支持 ```go // 设置超时上下文 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) defer cancel() // 在查询中使用上下文 var users []User err := userTable.Query(). WithContext(ctx). Where("status", "active"). Find(&users) // 在创建中使用上下文 options := &ixOrm.CreateOptions{ Context: ctx, } err = userTable.Create(user, options) ``` ### 错误处理 ixOrm 提供了智能的错误处理机制: ```go // 1. 数据库连接检查 userTable := client.Table("users") err := userTable.Find(&users) // 如果数据库连接未初始化,会返回 "数据库连接未初始化" 错误 // 2. 表不存在的处理 var users []User err = client.Table("nonexistent_table").Find(&users) // 表不存在时返回空结果,err == nil, users == [] // 3. 自动建表 user := &User{Name: "test"} err = client.Table("new_table").Create(user) // 如果表不存在,会自动创建表然后插入数据 ``` ## 🧪 测试 ### 运行测试 ```bash # 运行所有测试 go test -v ./tests/... # 运行特定测试 go test -v ./tests/config_test.go go test -v ./tests/charset_test.go go test -v ./tests/gorm_config_test.go # 运行集成测试(需要数据库环境) go test -v ./tests/integration_test.go # 生成测试覆盖率报告 go test -cover ./tests/... ``` ### 测试环境配置 集成测试需要真实的数据库和Redis环境: ```bash # MySQL docker run --name test-mysql -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=test_db -p 3306:3306 -d mysql:8.0 # Redis(如果测试缓存功能) docker run --name test-redis -p 6379:6379 -d redis:alpine ``` ## 🚀 最佳实践 ### 1. 配置管理 ```go // 推荐:使用配置选项函数 client, err := ixOrm.NewClient(ixOrm.DefaultConfig(), ixOrm.WithHost("localhost"), ixOrm.WithAuth("root", "password"), ixOrm.WithDatabase("production"), ixOrm.WithCharsetAndCollation("utf8mb4", "utf8mb4_unicode_ci"), ixOrm.WithConnectionPool(100, 20, time.Hour*2), ixOrm.WithGormPrepareStmt(true), ) // 或使用连接字符串 client, err := ixOrm.NewClient(ixOrm.DefaultConfig(), ixOrm.WithSqlConn("root:password@tcp(localhost:3306)/production?charset=utf8mb4"), ) ``` ### 2. 表名管理 ```go // 推荐:使用常量管理表名 const ( TableUsers = "users" TableOrders = "orders" TableProducts = "products" ) userTable := client.Table(TableUsers) ``` ### 3. 错误处理 ```go // 推荐:统一的错误处理 func handleError(operation string, err error) { if err != nil { log.Printf("%s操作失败: %v", operation, err) // 可以添加错误上报、告警等逻辑 } } err := userTable.Create(user) handleError("创建用户", err) ``` ### 4. 缓存策略 ```go // 推荐:为频繁查询的数据启用自动缓存 hotDataTable := client.Table("hot_products").WithCache(true) // 推荐:使用自定义缓存键和合适的过期时间 userListTable := client.Table("users").WithCache("user_list_v1", time.Minute*30) // 推荐:在更新后主动清除缓存 err = userTable.Where("id", userID).Update(updates) if err == nil { userTable.ClearCache() // 清除当前表的所有缓存 } ``` ### 5. 查询优化 ```go // 推荐:使用字段选择,避免查询不需要的数据 err := userTable.Query(). Select("id", "name", "email"). Where("status", "active"). Find(&users) // 推荐:使用分页限制结果集大小 result, err := userTable.Query(). Where("age > ?", 18). OrderBy("created_at"). Paginate(1, 50, &users) // 推荐:为复杂查询启用缓存 err := userTable.Query(). Where("department", "IT"). Where("level > ?", 3). WithCache(true). // 自动生成缓存键 Find(&users) ``` ### 6. 多实例使用 ```go // 主从分离示例 ixOrm.Add("master", masterConfig) ixOrm.Add("slave", slaveConfig) master, _ := ixOrm.Get("master") slave, _ := ixOrm.Get("slave") // 写操作使用主库 err = master.Table("users").Create(user) // 读操作使用从库,启用缓存 var users []User err = slave.Table("users").WithCache(true).Find(&users) ``` ## 🔧 高级特性 ### 自动建表机制 ```go // 当表不存在时,Create操作会自动创建表 type NewTable struct { ID uint `gorm:"primaryKey"` Name string `gorm:"size:100"` } // 第一次插入时会自动创建表 err := client.Table("new_table").Create(&NewTable{Name: "test"}) ``` ### 智能错误处理 ```go // 查询不存在的表时返回空数据,而不是错误 var users []User err := client.Table("nonexistent_table").Find(&users) // err == nil, users == [] // 数据库连接检查 err := client.Table("users").Find(&users) // 如果数据库连接未初始化,返回 "数据库连接未初始化" 错误 ``` ### 灵活的缓存键管理 ```go // 自动生成缓存键 userTable.WithCache(true) // 查看生成的缓存键(调试用) // 实际键:ixorm:user_db:production:users:find:status_active_created_at_10 // 清除特定表的缓存 userTable.ClearCache() // 使用模式删除 cache := client.GetCache() cache.DelPattern("*:users:*") // 删除所有users表相关缓存 cache.DelPattern("ixorm:*") // 删除所有ixorm缓存 ``` ## 📋 注意事项 1. **数据库连接**: 确保数据库服务正常运行,网络连接稳定 2. **表名管理**: 建议使用常量管理表名,避免硬编码 3. **缓存一致性**: 在数据更新时及时清除相关缓存 4. **错误处理**: 完善的错误处理和日志记录 5. **连接池配置**: 根据应用负载合理配置连接池参数 6. **上下文使用**: 为长时间操作设置合理的超时时间 7. **安全考虑**: 使用参数化查询防止SQL注入 8. **资源清理**: 应用关闭时正确关闭数据库连接 9. **字符集选择**: 新项目推荐使用 utf8mb4 支持完整Unicode 10. **GORM配置**: 生产环境建议启用 PrepareStmt 提升性能 ## 📊 性能优化 ### 1. 连接池优化 ```go config := ixOrm.DefaultConfig() ixOrm.WithConnectionPool( 200, // MaxOpenConns: 根据并发量调整 50, // MaxIdleConns: 通常为MaxOpenConns的1/4 time.Hour*4, // ConnMaxLifetime: 避免连接过期 )(config) ``` ### 2. GORM优化 ```go // 生产环境推荐配置 client, err := ixOrm.NewClient(config, ixOrm.WithGormPrepareStmt(true), // 启用预编译语句 ixOrm.WithGormCreateBatchSize(1000), // 设置批量大小 ixOrm.WithGormLogger(ixOrm.NewSilentGormLogger()), // 生产环境使用静默日志 ) ``` ### 3. 查询优化 ```go // 使用字段选择,避免查询不需要的数据 err := userTable.Query(). Select("id", "name", "email"). Where("status", "active"). Find(&users) // 使用分页限制结果集大小 result, err := userTable.Query(). OrderBy("created_at"). Paginate(1, 50, &users) ``` ### 4. 智能缓存优化 ```go // 为频繁查询的数据启用自动缓存 err := userTable.Query(). Where("role", "admin"). WithCache(true). // 自动生成缓存键 Find(&users) // 设置合适的缓存过期时间 // 热点数据:较长过期时间 userTable.WithCache("hot_users", time.Hour) // 实时数据:较短过期时间 userTable.WithCache("realtime_data", time.Minute*5) // 根据数据特性选择合适的缓存类型 // 静态配置数据:使用内存缓存(性能更好) err = userTable.Query(). Where("type", "config"). WithCache(true). WithCacheType(ixOrm.CacheTypeMemory). Find(&configs) // 用户会话数据:使用Redis缓存(支持集群) err = userTable.Query(). Where("session_id", sessionID). WithCache(true). WithCacheType(ixOrm.CacheTypeRedis). Find(&sessions) // 临时查询:不使用缓存(直接查询数据库) err = userTable.Query(). Where("created_at", ">", time.Now().Add(-time.Minute)). WithCacheType(ixOrm.CacheTypeNone). Find(&recentUsers) // 智能缓存策略:根据环境自动选择 if isProduction { client.SetDefaultCacheType(ixOrm.CacheTypeRedis) // 生产环境使用Redis } else { client.SetDefaultCacheType(ixOrm.CacheTypeMemory) // 开发环境使用内存缓存 } ``` #### 内存缓存最佳实践 1. **适用场景** - 单机应用或单实例部署 - 频繁读取的静态数据 - 对延迟敏感的热点数据 - 开发测试环境 2. **内存管理** ```go // 设置合理的TTL,避免内存泄漏 client, err := ixOrm.NewClient( ixOrm.WithMemoryCache(time.Minute*30), // 30分钟过期 ) // 定期清理不需要的缓存 userTable.ClearCache() // 表级别清理 ``` 3. **性能优化** ```go // 使用内存缓存进行批量查询 var users []User err := userTable.Query(). Where("department", "IT"). WithCache(true). WithCacheType(ixOrm.CacheTypeMemory). // 明确指定内存缓存 Find(&users) ``` 4. **监控和调试** ```go // 获取缓存实例进行监控 cache := client.GetCacheByType(ixOrm.CacheTypeMemory) if memoryCache, ok := cache.(*ixOrm.MemoryCache); ok { // 可以添加监控逻辑 fmt.Println("使用内存缓存") } ``` #### 同时使用两种缓存的最佳实践 1. **配置建议** ```go // 同时配置两种缓存,默认使用Redis client, err := ixOrm.NewClient( ixOrm.WithHost("localhost"), ixOrm.WithPort(3306), ixOrm.WithAuth("root", "password"), ixOrm.WithDatabase("test_db"), ixOrm.WithBothCaches([]interface{}{"localhost", 6379, "", 0}, time.Minute*10), ) // 检查缓存可用性 if client.HasRedisCache() && client.HasMemoryCache() { fmt.Println("两种缓存都可用,可以灵活选择") } ``` 2. **使用策略** ```go // 根据数据特性选择缓存类型 // 热点数据 -> 内存缓存(性能优先) // 重要数据 -> Redis缓存(持久化优先) // 临时数据 -> 不使用缓存(实时性优先) // 热点数据使用内存缓存 var hotUsers []User err := userTable.Query(). Where("status", "active"). WithCacheType(ixOrm.CacheTypeMemory). Find(&hotUsers) // 重要数据使用Redis缓存 var importantUsers []User err := userTable.Query(). Where("role", "admin"). WithCacheType(ixOrm.CacheTypeRedis). Find(&importantUsers) ``` 3. **动态切换** ```go // 根据运行环境动态切换默认缓存 if isProduction { client.SetDefaultCacheType(ixOrm.CacheTypeRedis) // 生产环境使用Redis } else { client.SetDefaultCacheType(ixOrm.CacheTypeMemory) // 开发环境使用内存缓存 } ``` 4. **监控和维护** ```go // 监控缓存状态 fmt.Printf("Redis缓存状态: %v\n", client.HasRedisCache()) fmt.Printf("内存缓存状态: %v\n", client.HasMemoryCache()) // 分别清理不同缓存 if client.HasRedisCache() { client.GetRedisCache().Clear() } if client.HasMemoryCache() { client.GetMemoryCache().Clear() } ``` ## 📖 使用示例 ### 完整示例 ```go package main import ( "context" "fmt" "log" "time" "gitee.com/ixgo/db" ) type User struct { ID uint `gorm:"primaryKey" json:"id"` Name string `gorm:"size:100;not null" json:"name"` Email string `gorm:"size:100;uniqueIndex" json:"email"` Age int `json:"age"` Status string `gorm:"size:20;default:'active'" json:"status"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } func main() { // 1. 配置数据库 config := ixOrm.DefaultConfig() client, err := ixOrm.NewClient(config, ixOrm.WithHost("localhost"), ixOrm.WithAuth("root", "password"), ixOrm.WithDatabase("demo"), ixOrm.WithCharsetAndCollation("utf8mb4", "utf8mb4_unicode_ci"), ixOrm.WithCache("localhost", 6379, "", 0, time.Minute*10), ixOrm.WithGormPrepareStmt(true), ) if err != nil { log.Fatal("连接数据库失败:", err) } defer client.Close() // 2. 获取表操作器 userTable := client.Table("users") // 3. 创建用户(自动建表) user := &User{ Name: "张三", Email: "zhangsan@example.com", Age: 25, Status: "active", } err = userTable.Create(user) if err != nil { log.Printf("创建用户失败: %v", err) } else { fmt.Printf("创建用户成功,ID: %d\n", user.ID) } // 4. 批量创建 users := []User{ {Name: "李四", Email: "lisi@example.com", Age: 30}, {Name: "王五", Email: "wangwu@example.com", Age: 28}, } err = userTable.CreateInBatches(users, 10) if err != nil { log.Printf("批量创建失败: %v", err) } // 5. Upsert 操作(插入或更新) upsertUser := &User{ ID: 1, // 如果ID=1存在则更新,不存在则插入 Name: "张三(更新)", Email: "zhangsan_updated@example.com", Age: 26, } err = userTable.Upsert(upsertUser) if err != nil { log.Printf("Upsert失败: %v", err) } else { fmt.Printf("Upsert成功,用户ID: %d\n", upsertUser.ID) } // 6. 链式查询(启用自动缓存) var activeUsers []User err = userTable.Query(). Where("status", "active"). Where("age > ?", 20). OrderByDesc("created_at"). WithCache(true). // 自动生成缓存键 Limit(10). Find(&activeUsers) if err != nil { log.Printf("查询失败: %v", err) } else { fmt.Printf("查询到 %d 个活跃用户\n", len(activeUsers)) } // 7. 分页查询 var pageUsers []User result, err := userTable.Query(). Where("age > ?", 18). OrderBy("name"). WithCache("adult_users", time.Minute*15). Paginate(1, 5, &pageUsers) if err != nil { log.Printf("分页查询失败: %v", err) } else { fmt.Printf("分页结果: 第%d页,共%d页,总计%d条记录\n", result.Page, result.TotalPages, result.Total) } // 8. 更新用户 err = userTable.Query(). Where("email", "zhangsan@example.com"). Update(map[string]interface{}{ "age": 26, "status": "premium", }) if err != nil { log.Printf("更新失败: %v", err) } else { fmt.Println("更新成功") // 清除相关缓存 userTable.ClearCache() } // 9. 计数和存在性检查 count, err := userTable.Query(). Where("status", "active"). Count() if err != nil { log.Printf("计数失败: %v", err) } else { fmt.Printf("活跃用户数: %d\n", count) } exists, err := userTable.Where("email", "test@example.com").Exists() if err != nil { log.Printf("检查失败: %v", err) } else { fmt.Printf("用户是否存在: %t\n", exists) } // 10. 使用上下文 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel() var ctxUsers []User err = userTable.Query(). WithContext(ctx). Where("status", "active"). WithCache("ctx_users"). Find(&ctxUsers) if err != nil { log.Printf("上下文查询失败: %v", err) } // 11. 删除用户 err = userTable.Query(). Where("status", "inactive"). Delete() // 软删除 if err != nil { log.Printf("删除失败: %v", err) } else { fmt.Println("删除成功") } fmt.Println("示例完成") } ``` ## 🤝 贡献指南 欢迎贡献代码!请遵循以下步骤: 1. Fork 项目 2. 创建特性分支 (`git checkout -b feature/AmazingFeature`) 3. 提交更改 (`git commit -m 'Add some AmazingFeature'`) 4. 推送到分支 (`git push origin feature/AmazingFeature`) 5. 打开 Pull Request ## 📄 许可证 本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。 ## 📞 支持 如果您遇到问题或有建议,请: 1. 查看文档和示例 2. 搜索现有的 Issues 3. 创建新的 Issue 描述问题 4. 参与讨论和改进 ## 📋 快速参考 ### 缓存配置速查表 | 配置方式 | 代码示例 | 说明 | |----------|----------|------| | **同时配置两种缓存** | `ixOrm.WithBothCaches([]interface{}{"localhost", 6379, "", 0}, time.Minute*10)` | 推荐方式,默认Redis | | **仅Redis缓存** | `ixOrm.WithCache("localhost", 6379, "", 0, time.Minute*10)` | 生产环境推荐 | | **仅内存缓存** | `ixOrm.WithMemoryCache(time.Minute*10)` | 开发环境推荐 | | **分别配置** | `ixOrm.WithCache(...) + ixOrm.WithMemoryCache(...)` | 灵活配置 | ### 缓存类型速查表 | 常量 | 值 | 说明 | |------|-----|------| | `ixOrm.CacheTypeRedis` | 0 | Redis缓存(默认) | | `ixOrm.CacheTypeMemory` | 1 | 内存缓存 | | `ixOrm.CacheTypeNone` | 2 | 不使用缓存 | ### 常用方法速查表 | 方法 | 说明 | |------|------| | `client.HasRedisCache()` | 检查Redis缓存是否可用 | | `client.HasMemoryCache()` | 检查内存缓存是否可用 | | `client.GetRedisCache()` | 获取Redis缓存实例 | | `client.GetMemoryCache()` | 获取内存缓存实例 | | `client.SetDefaultCacheType()` | 动态切换默认缓存类型 | | `table.WithCacheType()` | 指定查询使用的缓存类型 | --- **ixOrm** - 让数据库操作更简单、更安全、更高效! ## 🎉 最新更新 ### v1.1.0 (2024-10-21) **查询功能大幅增强** 🔍 - ✅ **修复 BUG**: 修复了 `!=`、`>=`、`<=`、`<>` 等操作符的判断问题 - 🆕 **LIKE 查询**: 新增 `WhereLike()` 和 `OrWhereLike()` 方法,支持模糊查询 - 🆕 **OR 条件**: 完整的 OR 条件支持 - `OrWhere()` - OR 等值查询 - `OrWhereIn()` - OR IN 查询 - `OrWhereLike()` - OR LIKE 查询 - `OrWhereNull()` / `OrWhereNotNull()` - OR NULL 判断 - `OrWhereBetween()` - OR BETWEEN 查询 - 🆕 **NULL 判断**: 新增 `WhereNull()` 和 `WhereNotNull()` 方法 - 🆕 **范围查询**: 新增 `WhereBetween()` 和 `WhereNotBetween()` 方法 - 🆕 **原始 SQL**: 新增 `WhereRaw()` 方法,支持复杂 SQL 表达式和子查询 **现在支持的查询类型**: - ✅ 等值查询、比较操作(`>`, `<`, `>=`, `<=`, `!=`, `<>`) - ✅ IN / NOT IN 查询 - ✅ LIKE 模糊查询 - ✅ NULL 判断(IS NULL / IS NOT NULL) - ✅ BETWEEN 范围查询 - ✅ OR 条件(支持所有查询类型) - ✅ 原始 SQL 表达式 - ✅ 复杂查询组合 ### v1.0.0 - 🚀 基础 CRUD 操作 - 💾 智能缓存系统(Redis + 内存缓存) - 🏢 多实例管理 - 🔗 链式查询操作 - 🛠 自动建表 - 📊 智能错误处理 --- > 🚀 **新功能**: 强大的查询构建器,支持 LIKE、OR 条件、NULL 判断、BETWEEN 范围查询和原始 SQL!