hotime/examples/hotimedb_examples.go

785 lines
21 KiB
Go
Raw Permalink Normal View History

package main
import (
"database/sql"
"fmt"
"log"
// 实际使用时请替换为正确的导入路径
// "code.hoteas.com/golang/hotime/cache"
// "code.hoteas.com/golang/hotime/common"
// "code.hoteas.com/golang/hotime/db"
"code.hoteas.com/golang/hotime/cache"
"code.hoteas.com/golang/hotime/common"
"code.hoteas.com/golang/hotime/db"
_ "github.com/go-sql-driver/mysql"
"github.com/sirupsen/logrus"
)
// HoTimeDB使用示例代码集合 - 修正版
// 本文件包含了各种常见场景的完整示例代码,所有条件查询语法已修正
// 示例1: 基本初始化和配置
func Example1_BasicSetup() {
// 创建数据库实例
database := &db.HoTimeDB{
Prefix: "app_", // 设置表前缀
Mode: 2, // 开发模式输出SQL日志
Type: "mysql", // 数据库类型
}
// 设置日志
logger := logrus.New()
database.Log = logger
// 设置连接函数
database.SetConnect(func(err ...*common.Error) (master, slave *sql.DB) {
// 主数据库连接
master, dbErr := sql.Open("mysql", "root:password@tcp(localhost:3306)/testdb?charset=utf8&parseTime=true")
if dbErr != nil {
log.Fatal("数据库连接失败:", dbErr)
}
// 从数据库连接(可选,用于读写分离)
slave = master // 这里使用同一个连接,实际项目中可以连接到从库
return master, slave
})
fmt.Println("数据库初始化完成")
}
// 示例2: 基本CRUD操作修正版
func Example2_BasicCRUD_Fixed(db *db.HoTimeDB) {
// 创建用户
fmt.Println("=== 创建用户 ===")
userId := db.Insert("user", common.Map{
"name": "张三",
"email": "zhangsan@example.com",
"age": 25,
"status": 1,
"balance": 1000.50,
"created_time[#]": "NOW()",
})
fmt.Printf("新用户ID: %d\n", userId)
// 查询用户单条件可以不用AND
fmt.Println("\n=== 查询用户 ===")
user := db.Get("user", "*", common.Map{
"id": userId,
})
if user != nil {
fmt.Printf("用户信息: %+v\n", user)
}
// 更新用户多条件必须用AND包装
fmt.Println("\n=== 更新用户 ===")
affected := db.Update("user", common.Map{
"name": "李四",
"age": 26,
"updated_time[#]": "NOW()",
}, common.Map{
"AND": common.Map{
"id": userId,
"status": 1, // 确保只更新正常状态的用户
},
})
fmt.Printf("更新记录数: %d\n", affected)
// 软删除用户
fmt.Println("\n=== 软删除用户 ===")
affected = db.Update("user", common.Map{
"deleted_at[#]": "NOW()",
"status": 0,
}, common.Map{
"id": userId, // 单条件不需要AND
})
fmt.Printf("软删除记录数: %d\n", affected)
}
// 示例3: 条件查询语法(修正版)
func Example3_ConditionQuery_Fixed(db *db.HoTimeDB) {
fmt.Println("=== 条件查询语法示例 ===")
// ✅ 正确:单个条件
users1 := db.Select("user", "*", common.Map{
"status": 1,
})
fmt.Printf("活跃用户: %d个\n", len(users1))
// ✅ 正确多个条件用AND包装
users2 := db.Select("user", "*", common.Map{
"AND": common.Map{
"status": 1,
"age[>]": 18,
"age[<=]": 60,
},
})
fmt.Printf("活跃的成年用户: %d个\n", len(users2))
// ✅ 正确OR条件
users3 := db.Select("user", "*", common.Map{
"OR": common.Map{
"level": "vip",
"balance[>]": 5000,
},
})
fmt.Printf("VIP或高余额用户: %d个\n", len(users3))
// ✅ 正确:条件 + 特殊参数
users4 := db.Select("user", "*", common.Map{
"AND": common.Map{
"status": 1,
"age[>=]": 18,
},
"ORDER": "created_time DESC",
"LIMIT": 10,
})
fmt.Printf("最近的活跃成年用户: %d个\n", len(users4))
// ✅ 正确:复杂嵌套条件
users5 := db.Select("user", "*", common.Map{
"AND": common.Map{
"status": 1,
"OR": common.Map{
"age[<]": 30,
"level": "vip",
},
},
"ORDER": []string{"level DESC", "created_time DESC"},
"LIMIT": []int{0, 20},
})
fmt.Printf("年轻或VIP的活跃用户: %d个\n", len(users5))
// ✅ 正确:模糊查询
users6 := db.Select("user", "*", common.Map{
"AND": common.Map{
"name[~]": "张", // 姓名包含"张"
"email[~!]": "gmail", // 邮箱以gmail开头
"status": 1,
},
})
fmt.Printf("姓张的gmail活跃用户: %d个\n", len(users6))
// ✅ 正确:范围查询
users7 := db.Select("user", "*", common.Map{
"AND": common.Map{
"age[<>]": []int{18, 35}, // 年龄在18-35之间
"balance[><]": []float64{0, 100}, // 余额不在0-100之间
"status": 1,
},
})
fmt.Printf("18-35岁且余额>100的活跃用户: %d个\n", len(users7))
// ✅ 正确IN查询
users8 := db.Select("user", "*", common.Map{
"AND": common.Map{
"id": []int{1, 2, 3, 4, 5}, // ID在指定范围内
"status[!]": []int{0, -1}, // 状态不为0或-1
},
})
fmt.Printf("指定ID的活跃用户: %d个\n", len(users8))
}
// 示例4: 链式查询操作(正确版)
func Example4_ChainQuery_Fixed(db *db.HoTimeDB) {
fmt.Println("=== 链式查询示例 ===")
// 链式查询链式语法允许单独的Where然后用And添加更多条件
users := db.Table("user").
Where("status", 1). // 链式中可以单独Where
And("age[>=]", 18). // 然后用And添加条件
And("age[<=]", 60). // 再添加条件
Or(common.Map{ // 或者用Or添加OR条件组
"level": "vip",
"balance[>]": 5000,
}).
Order("created_time DESC", "id ASC"). // 排序
Limit(0, 10). // 限制结果
Select("id,name,email,age,balance,level")
fmt.Printf("链式查询到 %d 个用户\n", len(users))
for i, user := range users {
fmt.Printf("用户%d: %s (年龄:%v, 余额:%v)\n",
i+1,
user.GetString("name"),
user.Get("age"),
user.Get("balance"))
}
// 链式统计查询
count := db.Table("user").
Where("status", 1).
And("age[>=]", 18).
Count()
fmt.Printf("符合条件的用户总数: %d\n", count)
}
// 示例5: JOIN查询操作修正版
func Example5_JoinQuery_Fixed(db *db.HoTimeDB) {
fmt.Println("=== JOIN查询示例 ===")
// 链式JOIN查询
orders := db.Table("order").
LeftJoin("user", "order.user_id = user.id").
LeftJoin("product", "order.product_id = product.id").
Where("order.status", "paid"). // 链式中单个条件可以直接Where
And("order.created_time[>]", "2023-01-01"). // 用And添加更多条件
Order("order.created_time DESC").
Select(`
order.id as order_id,
order.amount,
order.status,
order.created_time,
user.name as user_name,
user.email as user_email,
product.title as product_title,
product.price as product_price
`)
fmt.Printf("链式JOIN查询到 %d 个订单\n", len(orders))
for _, order := range orders {
fmt.Printf("订单ID:%v, 用户:%s, 商品:%s, 金额:%v\n",
order.Get("order_id"),
order.GetString("user_name"),
order.GetString("product_title"),
order.Get("amount"))
}
// 传统JOIN语法多个条件必须用AND包装
orders2 := db.Select("order",
common.Slice{
common.Map{"[>]user": "order.user_id = user.id"},
common.Map{"[>]product": "order.product_id = product.id"},
},
"order.*, user.name as user_name, product.title as product_title",
common.Map{
"AND": common.Map{
"order.status": "paid",
"order.created_time[>]": "2023-01-01",
},
})
fmt.Printf("传统JOIN语法查询到 %d 个订单\n", len(orders2))
}
// 示例6: 分页查询(修正版)
func Example6_PaginationQuery_Fixed(db *db.HoTimeDB) {
fmt.Println("=== 分页查询示例 ===")
page := 2
pageSize := 10
// 获取总数(单条件)
total := db.Count("user", common.Map{
"AND": common.Map{
"status": 1,
"deleted_at": nil,
},
})
// 分页数据(链式方式)
users := db.Table("user").
Where("status", 1).
And("deleted_at", nil).
Order("created_time DESC").
Page(page, pageSize).
Select("id,name,email,created_time")
// 使用传统方式的分页查询
users2 := db.Page(page, pageSize).PageSelect("user", "*", common.Map{
"AND": common.Map{
"status": 1,
"deleted_at": nil,
},
"ORDER": "created_time DESC",
})
// 计算分页信息
totalPages := (total + pageSize - 1) / pageSize
offset := (page - 1) * pageSize
fmt.Printf("总记录数: %d\n", total)
fmt.Printf("总页数: %d\n", totalPages)
fmt.Printf("当前页: %d\n", page)
fmt.Printf("每页大小: %d\n", pageSize)
fmt.Printf("偏移量: %d\n", offset)
fmt.Printf("链式查询当前页记录数: %d\n", len(users))
fmt.Printf("传统查询当前页记录数: %d\n", len(users2))
for i, user := range users {
fmt.Printf(" %d. %s (%s) - %v\n",
offset+i+1,
user.GetString("name"),
user.GetString("email"),
user.Get("created_time"))
}
}
// 示例7: 聚合函数查询(修正版)
func Example7_AggregateQuery_Fixed(db *db.HoTimeDB) {
fmt.Println("=== 聚合函数查询示例 ===")
// 基本统计
userCount := db.Count("user")
activeUserCount := db.Count("user", common.Map{"status": 1})
totalBalance := db.Sum("user", "balance", common.Map{"status": 1})
fmt.Printf("总用户数: %d\n", userCount)
fmt.Printf("活跃用户数: %d\n", activeUserCount)
fmt.Printf("活跃用户总余额: %.2f\n", totalBalance)
// 分组统计(正确语法)
stats := db.Select("user",
"level, COUNT(*) as user_count, AVG(age) as avg_age, SUM(balance) as total_balance",
common.Map{
"status": 1, // 单条件不需要AND
"GROUP": "level",
"ORDER": "user_count DESC",
})
fmt.Println("\n按等级分组统计:")
for _, stat := range stats {
fmt.Printf("等级:%v, 用户数:%v, 平均年龄:%v, 总余额:%v\n",
stat.Get("level"),
stat.Get("user_count"),
stat.Get("avg_age"),
stat.Get("total_balance"))
}
// 关联统计(修正版)
orderStats := db.Select("order",
common.Slice{
common.Map{"[>]user": "order.user_id = user.id"},
},
"user.level, COUNT(order.id) as order_count, SUM(order.amount) as total_amount",
common.Map{
"AND": common.Map{
"order.status": "paid",
"order.created_time[>]": "2023-01-01",
},
"GROUP": "user.level",
"ORDER": "total_amount DESC",
})
fmt.Println("\n用户等级订单统计:")
for _, stat := range orderStats {
fmt.Printf("等级:%v, 订单数:%v, 总金额:%v\n",
stat.Get("level"),
stat.Get("order_count"),
stat.Get("total_amount"))
}
}
// 示例8: 事务处理(修正版)
func Example8_Transaction_Fixed(db *db.HoTimeDB) {
fmt.Println("=== 事务处理示例 ===")
// 模拟转账操作
fromUserId := int64(1)
toUserId := int64(2)
amount := 100.0
success := db.Action(func(tx db.HoTimeDB) bool {
// 检查转出账户余额(单条件)
fromUser := tx.Get("user", "balance", common.Map{"id": fromUserId})
if fromUser == nil {
fmt.Println("转出用户不存在")
return false
}
fromBalance := fromUser.GetFloat64("balance")
if fromBalance < amount {
fmt.Println("余额不足")
return false
}
// 扣减转出账户余额多条件必须用AND
affected1 := tx.Update("user", common.Map{
"balance[#]": fmt.Sprintf("balance - %.2f", amount),
"updated_time[#]": "NOW()",
}, common.Map{
"AND": common.Map{
"id": fromUserId,
"balance[>=]": amount, // 再次确保余额足够
},
})
if affected1 == 0 {
fmt.Println("扣减余额失败")
return false
}
// 增加转入账户余额(单条件)
affected2 := tx.Update("user", common.Map{
"balance[#]": fmt.Sprintf("balance + %.2f", amount),
"updated_time[#]": "NOW()",
}, common.Map{
"id": toUserId,
})
if affected2 == 0 {
fmt.Println("增加余额失败")
return false
}
// 记录转账日志
logId := tx.Insert("transfer_log", common.Map{
"from_user_id": fromUserId,
"to_user_id": toUserId,
"amount": amount,
"status": "success",
"created_time[#]": "NOW()",
})
if logId == 0 {
fmt.Println("记录日志失败")
return false
}
fmt.Printf("转账成功: 用户%d -> 用户%d, 金额:%.2f\n", fromUserId, toUserId, amount)
return true
})
if success {
fmt.Println("事务执行成功")
} else {
fmt.Println("事务回滚")
if db.LastErr.GetError() != nil {
fmt.Println("错误原因:", db.LastErr.GetError())
}
}
}
// 示例9: 缓存机制(修正版)
func Example9_CacheSystem_Fixed(db *db.HoTimeDB) {
fmt.Println("=== 缓存机制示例 ===")
// 设置缓存(实际项目中需要配置缓存参数)
db.HoTimeCache = &cache.HoTimeCache{}
// 第一次查询(会缓存结果)
fmt.Println("第一次查询(会缓存)...")
users1 := db.Select("user", "*", common.Map{
"status": 1, // 单条件
"LIMIT": 10,
})
fmt.Printf("查询到 %d 个用户\n", len(users1))
// 第二次相同查询(从缓存获取)
fmt.Println("第二次相同查询(从缓存获取)...")
users2 := db.Select("user", "*", common.Map{
"status": 1, // 单条件
"LIMIT": 10,
})
fmt.Printf("查询到 %d 个用户\n", len(users2))
// 更新操作会清除缓存
fmt.Println("执行更新操作(会清除缓存)...")
affected := db.Update("user", common.Map{
"updated_time[#]": "NOW()",
}, common.Map{
"id": 1, // 单条件
})
fmt.Printf("更新 %d 条记录\n", affected)
// 再次查询(重新从数据库获取并缓存)
fmt.Println("更新后再次查询(重新缓存)...")
users3 := db.Select("user", "*", common.Map{
"status": 1, // 单条件
"LIMIT": 10,
})
fmt.Printf("查询到 %d 个用户\n", len(users3))
}
// 示例10: 性能优化技巧(修正版)
func Example10_PerformanceOptimization_Fixed(db *db.HoTimeDB) {
fmt.Println("=== 性能优化技巧示例 ===")
// IN查询优化连续数字自动转为BETWEEN
fmt.Println("IN查询优化示例...")
users := db.Select("user", "*", common.Map{
"id": []int{1, 2, 3, 4, 5, 10, 11, 12, 13, 20}, // 单个IN条件会被优化
})
fmt.Printf("查询到 %d 个用户\n", len(users))
fmt.Println("执行的SQL:", db.LastQuery)
// 批量插入(使用事务)
fmt.Println("\n批量插入示例...")
success := db.Action(func(tx db.HoTimeDB) bool {
for i := 1; i <= 100; i++ {
id := tx.Insert("user_batch", common.Map{
"name": fmt.Sprintf("批量用户%d", i),
"email": fmt.Sprintf("batch%d@example.com", i),
"status": 1,
"created_time[#]": "NOW()",
})
if id == 0 {
return false
}
// 每10个用户输出一次进度
if i%10 == 0 {
fmt.Printf("已插入 %d 个用户\n", i)
}
}
return true
})
if success {
fmt.Println("批量插入完成")
} else {
fmt.Println("批量插入失败")
}
// 索引友好的查询(修正版)
fmt.Println("\n索引友好的查询...")
recentUsers := db.Select("user", "*", common.Map{
"AND": common.Map{
"created_time[>]": "2023-01-01", // 假设created_time有索引
"status": 1, // 假设status有索引
},
"ORDER": "created_time DESC", // 利用索引排序
"LIMIT": 20,
})
fmt.Printf("查询到 %d 个近期用户\n", len(recentUsers))
}
// 完整的应用示例(修正版)
func CompleteExample_Fixed() {
fmt.Println("=== HoTimeDB完整应用示例修正版 ===")
// 初始化数据库
database := &db.HoTimeDB{
Prefix: "app_",
Mode: 1, // 测试模式
Type: "mysql",
}
// 设置连接
database.SetConnect(func(err ...*common.Error) (master, slave *sql.DB) {
// 这里使用实际的数据库连接字符串
dsn := "root:password@tcp(localhost:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
master, dbErr := sql.Open("mysql", dsn)
if dbErr != nil {
log.Fatal("数据库连接失败:", dbErr)
}
return master, master
})
// 用户管理系统示例
fmt.Println("\n=== 用户管理系统 ===")
// 1. 创建用户
userId := database.Insert("user", common.Map{
"name": "示例用户",
"email": "example@test.com",
"password": "hashed_password",
"age": 28,
"status": 1,
"level": "normal",
"balance": 500.00,
"created_time[#]": "NOW()",
})
fmt.Printf("创建用户成功ID: %d\n", userId)
// 2. 用户登录更新多条件用AND
database.Update("user", common.Map{
"last_login[#]": "NOW()",
"login_count[#]": "login_count + 1",
}, common.Map{
"AND": common.Map{
"id": userId,
"status": 1,
},
})
// 3. 创建订单
orderId := database.Insert("order", common.Map{
"user_id": userId,
"amount": 299.99,
"status": "pending",
"created_time[#]": "NOW()",
})
fmt.Printf("创建订单成功ID: %d\n", orderId)
// 4. 订单支付(使用事务,修正版)
paymentSuccess := database.Action(func(tx db.HoTimeDB) bool {
// 更新订单状态(单条件)
affected1 := tx.Update("order", common.Map{
"status": "paid",
"paid_time[#]": "NOW()",
}, common.Map{
"id": orderId,
})
if affected1 == 0 {
return false
}
// 扣减用户余额多条件用AND
affected2 := tx.Update("user", common.Map{
"balance[#]": "balance - 299.99",
}, common.Map{
"AND": common.Map{
"id": userId,
"balance[>=]": 299.99, // 确保余额足够
},
})
if affected2 == 0 {
fmt.Println("余额不足或用户不存在")
return false
}
// 记录支付日志
logId := tx.Insert("payment_log", common.Map{
"user_id": userId,
"order_id": orderId,
"amount": 299.99,
"type": "order_payment",
"status": "success",
"created_time[#]": "NOW()",
})
return logId > 0
})
if paymentSuccess {
fmt.Println("订单支付成功")
} else {
fmt.Println("订单支付失败")
}
// 5. 查询用户订单列表(链式查询)
userOrders := database.Table("order").
LeftJoin("user", "order.user_id = user.id").
Where("order.user_id", userId). // 链式中单个条件可以直接Where
Order("order.created_time DESC").
Select(`
order.id,
order.amount,
order.status,
order.created_time,
order.paid_time,
user.name as user_name
`)
fmt.Printf("\n用户订单列表 (%d个订单):\n", len(userOrders))
for _, order := range userOrders {
fmt.Printf(" 订单ID:%v, 金额:%v, 状态:%s, 创建时间:%v\n",
order.Get("id"),
order.Get("amount"),
order.GetString("status"),
order.Get("created_time"))
}
// 6. 生成统计报表(修正版)
stats := database.Select("order",
common.Slice{
common.Map{"[>]user": "order.user_id = user.id"},
},
`
DATE(order.created_time) as date,
COUNT(order.id) as order_count,
SUM(order.amount) as total_amount,
AVG(order.amount) as avg_amount
`,
common.Map{
"AND": common.Map{
"order.status": "paid",
"order.created_time[>]": "2023-01-01",
},
"GROUP": "DATE(order.created_time)",
"ORDER": "date DESC",
"LIMIT": 30,
})
fmt.Printf("\n最近30天订单统计:\n")
for _, stat := range stats {
fmt.Printf("日期:%v, 订单数:%v, 总金额:%v, 平均金额:%v\n",
stat.Get("date"),
stat.Get("order_count"),
stat.Get("total_amount"),
stat.Get("avg_amount"))
}
fmt.Println("\n示例执行完成")
}
// 语法对比示例
func SyntaxComparison() {
fmt.Println("=== HoTimeDB语法对比 ===")
// 模拟数据库对象
var db *db.HoTimeDB
fmt.Println("❌ 错误语法示例(不支持):")
fmt.Println(`
// 这样写是错误的多个条件不能直接放在根Map中
wrongUsers := db.Select("user", "*", common.Map{
"status": 1, // ❌ 错误
"age[>]": 18, // ❌ 错误
"ORDER": "id DESC",
})
`)
fmt.Println("✅ 正确语法示例:")
fmt.Println(`
// 单个条件可以直接写
correctUsers1 := db.Select("user", "*", common.Map{
"status": 1, // ✅ 正确,单个条件
})
// 多个条件必须用AND包装
correctUsers2 := db.Select("user", "*", common.Map{
"AND": common.Map{ // ✅ 正确多个条件用AND包装
"status": 1,
"age[>]": 18,
},
"ORDER": "id DESC", // ✅ 正确,特殊参数与条件同级
})
// OR条件
correctUsers3 := db.Select("user", "*", common.Map{
"OR": common.Map{ // ✅ 正确OR条件
"level": "vip",
"balance[>]": 1000,
},
})
// 嵌套条件
correctUsers4 := db.Select("user", "*", common.Map{
"AND": common.Map{ // ✅ 正确,嵌套条件
"status": 1,
"OR": common.Map{
"age[<]": 30,
"level": "vip",
},
},
"ORDER": "created_time DESC",
"LIMIT": 20,
})
`)
// 实际不执行查询,只是展示语法
_ = db
}
// 运行所有修正后的示例
func RunAllFixedExamples() {
fmt.Println("开始运行HoTimeDB所有修正后的示例...")
fmt.Println("注意:实际运行时需要确保数据库连接正确,并且相关表存在")
// 展示语法对比
SyntaxComparison()
fmt.Println("请根据实际环境配置数据库连接后运行相应示例")
fmt.Println("所有示例代码已修正完毕,语法正确!")
}
func main() {
// 运行语法对比示例
RunAllFixedExamples()
}