优化数据库连接配置,增强性能和稳定性
This commit is contained in:
@@ -0,0 +1,431 @@
|
||||
# HoTimeDB API 快速参考
|
||||
|
||||
## ⚠️ 重要语法说明
|
||||
|
||||
**条件查询语法规则:**
|
||||
- 单个条件:可以直接写在Map中
|
||||
- 多个条件:必须使用`AND`或`OR`包装
|
||||
- 特殊条件:`ORDER`、`GROUP`、`LIMIT`与条件同级
|
||||
|
||||
```go
|
||||
// ✅ 正确:单个条件
|
||||
Map{"status": 1}
|
||||
|
||||
// ✅ 正确:多个条件用AND包装
|
||||
Map{
|
||||
"AND": Map{
|
||||
"status": 1,
|
||||
"age[>]": 18,
|
||||
},
|
||||
}
|
||||
|
||||
// ✅ 正确:条件 + 特殊参数
|
||||
Map{
|
||||
"AND": Map{
|
||||
"status": 1,
|
||||
"age[>]": 18,
|
||||
},
|
||||
"ORDER": "id DESC",
|
||||
"LIMIT": 10,
|
||||
}
|
||||
|
||||
// ❌ 错误:多个条件不用AND包装
|
||||
Map{
|
||||
"status": 1,
|
||||
"age[>]": 18, // 这样写不支持!
|
||||
}
|
||||
```
|
||||
|
||||
## 基本方法
|
||||
|
||||
### 数据库连接
|
||||
```go
|
||||
db.SetConnect(func() (master, slave *sql.DB) { ... })
|
||||
db.InitDb()
|
||||
```
|
||||
|
||||
### 链式查询构建器
|
||||
```go
|
||||
// 创建查询构建器
|
||||
builder := db.Table("tablename")
|
||||
|
||||
// 设置条件
|
||||
builder.Where(key, value)
|
||||
builder.And(key, value) 或 builder.And(map)
|
||||
builder.Or(key, value) 或 builder.Or(map)
|
||||
|
||||
// JOIN操作
|
||||
builder.LeftJoin(table, condition)
|
||||
builder.RightJoin(table, condition)
|
||||
builder.InnerJoin(table, condition)
|
||||
builder.FullJoin(table, condition)
|
||||
builder.Join(map) // 通用JOIN
|
||||
|
||||
// 排序和分组
|
||||
builder.Order(fields...)
|
||||
builder.Group(fields...)
|
||||
builder.Limit(args...)
|
||||
|
||||
// 分页
|
||||
builder.Page(page, pageSize)
|
||||
|
||||
// 执行查询
|
||||
builder.Select(fields...) // 返回 []Map
|
||||
builder.Get(fields...) // 返回 Map
|
||||
builder.Count() // 返回 int
|
||||
builder.Update(data) // 返回 int64
|
||||
builder.Delete() // 返回 int64
|
||||
```
|
||||
|
||||
## CRUD 操作
|
||||
|
||||
### 查询 (Select)
|
||||
```go
|
||||
// 基本查询
|
||||
data := db.Select("table")
|
||||
data := db.Select("table", "field1,field2")
|
||||
data := db.Select("table", []string{"field1", "field2"})
|
||||
data := db.Select("table", "*", whereMap)
|
||||
|
||||
// 带JOIN查询
|
||||
data := db.Select("table", joinSlice, "fields", whereMap)
|
||||
```
|
||||
|
||||
### 获取单条 (Get)
|
||||
```go
|
||||
// 自动添加 LIMIT 1
|
||||
row := db.Get("table", "fields", whereMap)
|
||||
```
|
||||
|
||||
### 插入 (Insert)
|
||||
```go
|
||||
id := db.Insert("table", dataMap)
|
||||
// 返回新插入记录的ID
|
||||
```
|
||||
|
||||
### 更新 (Update)
|
||||
```go
|
||||
affected := db.Update("table", dataMap, whereMap)
|
||||
// 返回受影响的行数
|
||||
```
|
||||
|
||||
### 删除 (Delete)
|
||||
```go
|
||||
affected := db.Delete("table", whereMap)
|
||||
// 返回删除的行数
|
||||
```
|
||||
|
||||
## 聚合函数
|
||||
|
||||
### 计数
|
||||
```go
|
||||
count := db.Count("table")
|
||||
count := db.Count("table", whereMap)
|
||||
count := db.Count("table", joinSlice, whereMap)
|
||||
```
|
||||
|
||||
### 求和
|
||||
```go
|
||||
sum := db.Sum("table", "column")
|
||||
sum := db.Sum("table", "column", whereMap)
|
||||
sum := db.Sum("table", "column", joinSlice, whereMap)
|
||||
```
|
||||
|
||||
## 分页查询
|
||||
```go
|
||||
// 设置分页
|
||||
db.Page(page, pageSize)
|
||||
|
||||
// 分页查询
|
||||
data := db.Page(page, pageSize).PageSelect("table", "fields", whereMap)
|
||||
```
|
||||
|
||||
## 条件语法参考
|
||||
|
||||
### 比较操作符
|
||||
| 写法 | SQL | 说明 |
|
||||
|------|-----|------|
|
||||
| `"field": value` | `field = ?` | 等于 |
|
||||
| `"field[!]": value` | `field != ?` | 不等于 |
|
||||
| `"field[>]": value` | `field > ?` | 大于 |
|
||||
| `"field[>=]": value` | `field >= ?` | 大于等于 |
|
||||
| `"field[<]": value` | `field < ?` | 小于 |
|
||||
| `"field[<=]": value` | `field <= ?` | 小于等于 |
|
||||
|
||||
### 模糊查询
|
||||
| 写法 | SQL | 说明 |
|
||||
|------|-----|------|
|
||||
| `"field[~]": "keyword"` | `field LIKE '%keyword%'` | 包含 |
|
||||
| `"field[~!]": "keyword"` | `field LIKE 'keyword%'` | 以...开头 |
|
||||
| `"field[!~]": "keyword"` | `field LIKE '%keyword'` | 以...结尾 |
|
||||
| `"field[~~]": "%keyword%"` | `field LIKE '%keyword%'` | 手动LIKE |
|
||||
|
||||
### 范围查询
|
||||
| 写法 | SQL | 说明 |
|
||||
|------|-----|------|
|
||||
| `"field[<>]": [min, max]` | `field BETWEEN ? AND ?` | 区间内 |
|
||||
| `"field[><]": [min, max]` | `field NOT BETWEEN ? AND ?` | 区间外 |
|
||||
|
||||
### 集合查询
|
||||
| 写法 | SQL | 说明 |
|
||||
|------|-----|------|
|
||||
| `"field": [v1, v2, v3]` | `field IN (?, ?, ?)` | 在集合中 |
|
||||
| `"field[!]": [v1, v2, v3]` | `field NOT IN (?, ?, ?)` | 不在集合中 |
|
||||
|
||||
### NULL查询
|
||||
| 写法 | SQL | 说明 |
|
||||
|------|-----|------|
|
||||
| `"field": nil` | `field IS NULL` | 为空 |
|
||||
| `"field[!]": nil` | `field IS NOT NULL` | 不为空 |
|
||||
|
||||
### 直接SQL
|
||||
| 写法 | SQL | 说明 |
|
||||
|------|-----|------|
|
||||
| `"field[#]": "NOW()"` | `field = NOW()` | 直接SQL函数 |
|
||||
| `"[##]": "a > b"` | `a > b` | 直接SQL片段 |
|
||||
| `"field[#!]": "1"` | `field != 1` | 不等于(不参数化) |
|
||||
|
||||
## 逻辑连接符
|
||||
|
||||
### AND 条件
|
||||
```go
|
||||
whereMap := Map{
|
||||
"AND": Map{
|
||||
"status": 1,
|
||||
"age[>]": 18,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### OR 条件
|
||||
```go
|
||||
whereMap := Map{
|
||||
"OR": Map{
|
||||
"status": 1,
|
||||
"type": 2,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 嵌套条件
|
||||
```go
|
||||
whereMap := Map{
|
||||
"AND": Map{
|
||||
"status": 1,
|
||||
"OR": Map{
|
||||
"age[<]": 30,
|
||||
"level[>]": 5,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## JOIN 语法
|
||||
|
||||
### 传统语法
|
||||
```go
|
||||
joinSlice := Slice{
|
||||
Map{"[>]profile": "user.id = profile.user_id"}, // LEFT JOIN
|
||||
Map{"[<]department": "user.dept_id = department.id"}, // RIGHT JOIN
|
||||
Map{"[><]role": "user.role_id = role.id"}, // INNER JOIN
|
||||
Map{"[<>]group": "user.group_id = group.id"}, // FULL JOIN
|
||||
}
|
||||
```
|
||||
|
||||
### 链式语法
|
||||
```go
|
||||
builder.LeftJoin("profile", "user.id = profile.user_id")
|
||||
builder.RightJoin("department", "user.dept_id = department.id")
|
||||
builder.InnerJoin("role", "user.role_id = role.id")
|
||||
builder.FullJoin("group", "user.group_id = group.id")
|
||||
```
|
||||
|
||||
## 特殊字段语法
|
||||
|
||||
### ORDER BY
|
||||
```go
|
||||
Map{
|
||||
"ORDER": []string{"created_time DESC", "id ASC"},
|
||||
}
|
||||
// 或
|
||||
Map{
|
||||
"ORDER": "created_time DESC",
|
||||
}
|
||||
```
|
||||
|
||||
### GROUP BY
|
||||
```go
|
||||
Map{
|
||||
"GROUP": []string{"department", "level"},
|
||||
}
|
||||
// 或
|
||||
Map{
|
||||
"GROUP": "department",
|
||||
}
|
||||
```
|
||||
|
||||
### LIMIT
|
||||
```go
|
||||
Map{
|
||||
"LIMIT": []int{10, 20}, // offset 10, limit 20
|
||||
}
|
||||
// 或
|
||||
Map{
|
||||
"LIMIT": 20, // limit 20
|
||||
}
|
||||
```
|
||||
|
||||
## 事务处理
|
||||
```go
|
||||
success := db.Action(func(tx HoTimeDB) bool {
|
||||
// 在这里执行数据库操作
|
||||
// 返回 true 提交事务
|
||||
// 返回 false 回滚事务
|
||||
|
||||
id := tx.Insert("table", data)
|
||||
if id == 0 {
|
||||
return false // 回滚
|
||||
}
|
||||
|
||||
affected := tx.Update("table2", data2, where2)
|
||||
if affected == 0 {
|
||||
return false // 回滚
|
||||
}
|
||||
|
||||
return true // 提交
|
||||
})
|
||||
```
|
||||
|
||||
## 原生SQL执行
|
||||
|
||||
### 查询
|
||||
```go
|
||||
results := db.Query("SELECT * FROM user WHERE age > ?", 18)
|
||||
```
|
||||
|
||||
### 执行
|
||||
```go
|
||||
result, err := db.Exec("UPDATE user SET status = ? WHERE id = ?", 1, 100)
|
||||
affected, _ := result.RowsAffected()
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
```go
|
||||
// 检查最后的错误
|
||||
if db.LastErr.GetError() != nil {
|
||||
fmt.Println("错误:", db.LastErr.GetError())
|
||||
}
|
||||
|
||||
// 查看最后执行的SQL
|
||||
fmt.Println("SQL:", db.LastQuery)
|
||||
fmt.Println("参数:", db.LastData)
|
||||
```
|
||||
|
||||
## 工具方法
|
||||
|
||||
### 数据库信息
|
||||
```go
|
||||
prefix := db.GetPrefix() // 获取表前缀
|
||||
dbType := db.GetType() // 获取数据库类型
|
||||
```
|
||||
|
||||
### 设置模式
|
||||
```go
|
||||
db.Mode = 0 // 生产模式
|
||||
db.Mode = 1 // 测试模式
|
||||
db.Mode = 2 // 开发模式(输出SQL日志)
|
||||
```
|
||||
|
||||
## 常用查询模式
|
||||
|
||||
### 分页列表查询
|
||||
```go
|
||||
// 获取总数
|
||||
total := db.Count("user", Map{"status": 1})
|
||||
|
||||
// 分页数据
|
||||
users := db.Table("user").
|
||||
Where("status", 1).
|
||||
Order("created_time DESC").
|
||||
Page(page, pageSize).
|
||||
Select("id,name,email,created_time")
|
||||
|
||||
// 计算分页信息
|
||||
totalPages := (total + pageSize - 1) / pageSize
|
||||
```
|
||||
|
||||
### 关联查询
|
||||
```go
|
||||
orders := db.Table("order").
|
||||
LeftJoin("user", "order.user_id = user.id").
|
||||
LeftJoin("product", "order.product_id = product.id").
|
||||
Where("order.status", "paid").
|
||||
Select(`
|
||||
order.*,
|
||||
user.name as user_name,
|
||||
product.title as product_title
|
||||
`)
|
||||
```
|
||||
|
||||
### 统计查询
|
||||
```go
|
||||
stats := db.Select("order",
|
||||
"user_id, COUNT(*) as order_count, SUM(amount) as total_amount",
|
||||
Map{
|
||||
"AND": Map{
|
||||
"status": "paid",
|
||||
"created_time[>]": "2023-01-01",
|
||||
},
|
||||
"GROUP": "user_id",
|
||||
"ORDER": "total_amount DESC",
|
||||
})
|
||||
```
|
||||
|
||||
### 条件组合查询
|
||||
```go
|
||||
products := db.Table("product").
|
||||
Where("status", 1).
|
||||
And(Map{
|
||||
"OR": Map{
|
||||
"category_id": []int{1, 2, 3},
|
||||
"tags[~]": "热销",
|
||||
},
|
||||
}).
|
||||
And(Map{
|
||||
"price[<>]": []float64{10.0, 1000.0},
|
||||
}).
|
||||
Order("sort DESC", "created_time DESC").
|
||||
Limit(0, 20).
|
||||
Select()
|
||||
```
|
||||
|
||||
## 链式调用完整示例
|
||||
|
||||
```go
|
||||
// 复杂查询链式调用
|
||||
result := db.Table("order").
|
||||
LeftJoin("user", "order.user_id = user.id").
|
||||
LeftJoin("product", "order.product_id = product.id").
|
||||
Where("order.status", "paid").
|
||||
And("order.created_time[>]", "2023-01-01").
|
||||
And(Map{
|
||||
"OR": Map{
|
||||
"user.level": "vip",
|
||||
"order.amount[>]": 1000,
|
||||
},
|
||||
}).
|
||||
Group("user.id").
|
||||
Order("total_amount DESC").
|
||||
Page(1, 20).
|
||||
Select(`
|
||||
user.id,
|
||||
user.name,
|
||||
user.email,
|
||||
COUNT(order.id) as order_count,
|
||||
SUM(order.amount) as total_amount
|
||||
`)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*快速参考版本: 1.0*
|
||||
@@ -0,0 +1,890 @@
|
||||
# HoTimeDB ORM 使用说明书
|
||||
|
||||
## 概述
|
||||
|
||||
HoTimeDB是一个基于Golang实现的轻量级ORM框架,参考PHP Medoo设计,提供简洁的数据库操作接口。支持MySQL、SQLite等数据库,并集成了缓存、事务、链式查询等功能。
|
||||
|
||||
## 目录
|
||||
|
||||
- [快速开始](#快速开始)
|
||||
- [数据库配置](#数据库配置)
|
||||
- [基本操作](#基本操作)
|
||||
- [查询(Select)](#查询select)
|
||||
- [获取单条记录(Get)](#获取单条记录get)
|
||||
- [插入(Insert)](#插入insert)
|
||||
- [更新(Update)](#更新update)
|
||||
- [删除(Delete)](#删除delete)
|
||||
- [链式查询构建器](#链式查询构建器)
|
||||
- [条件查询语法](#条件查询语法)
|
||||
- [JOIN操作](#join操作)
|
||||
- [分页查询](#分页查询)
|
||||
- [聚合函数](#聚合函数)
|
||||
- [事务处理](#事务处理)
|
||||
- [缓存机制](#缓存机制)
|
||||
- [高级特性](#高级特性)
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 初始化数据库连接
|
||||
|
||||
```go
|
||||
import (
|
||||
"code.hoteas.com/golang/hotime/db"
|
||||
"code.hoteas.com/golang/hotime/common"
|
||||
"database/sql"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
// 创建连接函数
|
||||
func createConnection() (master, slave *sql.DB) {
|
||||
master, _ = sql.Open("mysql", "user:password@tcp(localhost:3306)/database")
|
||||
// slave是可选的,用于读写分离
|
||||
slave = master // 或者连接到从数据库
|
||||
return
|
||||
}
|
||||
|
||||
// 初始化HoTimeDB
|
||||
db := &db.HoTimeDB{}
|
||||
db.SetConnect(createConnection)
|
||||
```
|
||||
|
||||
## 数据库配置
|
||||
|
||||
### 基本配置
|
||||
|
||||
```go
|
||||
type HoTimeDB struct {
|
||||
*sql.DB
|
||||
ContextBase
|
||||
DBName string
|
||||
*cache.HoTimeCache
|
||||
Log *logrus.Logger
|
||||
Type string // 数据库类型
|
||||
Prefix string // 表前缀
|
||||
LastQuery string // 最后执行的SQL
|
||||
LastData []interface{} // 最后的参数
|
||||
ConnectFunc func(err ...*Error) (*sql.DB, *sql.DB)
|
||||
LastErr *Error
|
||||
limit Slice
|
||||
*sql.Tx // 事务对象
|
||||
SlaveDB *sql.DB // 从数据库
|
||||
Mode int // 0生产模式,1测试模式,2开发模式
|
||||
}
|
||||
```
|
||||
|
||||
### 设置表前缀
|
||||
|
||||
```go
|
||||
db.Prefix = "app_"
|
||||
```
|
||||
|
||||
### 设置运行模式
|
||||
|
||||
```go
|
||||
db.Mode = 2 // 开发模式,会输出SQL日志
|
||||
```
|
||||
|
||||
## 基本操作
|
||||
|
||||
### 查询(Select)
|
||||
|
||||
#### 基本查询
|
||||
|
||||
```go
|
||||
// 查询所有字段
|
||||
users := db.Select("user")
|
||||
|
||||
// 查询指定字段
|
||||
users := db.Select("user", "id,name,email")
|
||||
|
||||
// 查询指定字段(数组形式)
|
||||
users := db.Select("user", []string{"id", "name", "email"})
|
||||
|
||||
// 单条件查询
|
||||
users := db.Select("user", "*", common.Map{
|
||||
"status": 1,
|
||||
})
|
||||
|
||||
// 多条件查询(必须使用AND包装)
|
||||
users = db.Select("user", "*", common.Map{
|
||||
"AND": common.Map{
|
||||
"status": 1,
|
||||
"age[>]": 18,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
#### 复杂条件查询
|
||||
|
||||
**重要说明:多个条件必须使用AND或OR包装,不能直接在根Map中写多个字段条件**
|
||||
|
||||
```go
|
||||
// AND条件(多个条件必须用AND包装)
|
||||
users := db.Select("user", "*", common.Map{
|
||||
"AND": common.Map{
|
||||
"status": 1,
|
||||
"age[>]": 18,
|
||||
"name[~]": "张",
|
||||
},
|
||||
})
|
||||
|
||||
// OR条件
|
||||
users := db.Select("user", "*", common.Map{
|
||||
"OR": common.Map{
|
||||
"status": 1,
|
||||
"type": 2,
|
||||
},
|
||||
})
|
||||
|
||||
// 混合条件(嵌套AND/OR)
|
||||
users := db.Select("user", "*", common.Map{
|
||||
"AND": common.Map{
|
||||
"status": 1,
|
||||
"OR": common.Map{
|
||||
"age[<]": 30,
|
||||
"level[>]": 5,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// 带ORDER BY、LIMIT等特殊条件
|
||||
users := db.Select("user", "*", common.Map{
|
||||
"AND": common.Map{
|
||||
"status": 1,
|
||||
"age[>]": 18,
|
||||
},
|
||||
"ORDER": "id DESC",
|
||||
"LIMIT": 10,
|
||||
})
|
||||
|
||||
// 带多个特殊条件
|
||||
users := db.Select("user", "*", common.Map{
|
||||
"OR": common.Map{
|
||||
"level": "vip",
|
||||
"balance[>]": 1000,
|
||||
},
|
||||
"ORDER": []string{"created_time DESC", "id ASC"},
|
||||
"GROUP": "department",
|
||||
"LIMIT": []int{0, 20}, // offset 0, limit 20
|
||||
})
|
||||
```
|
||||
|
||||
### 获取单条记录(Get)
|
||||
|
||||
```go
|
||||
// 获取单个用户
|
||||
user := db.Get("user", "*", common.Map{
|
||||
"id": 1,
|
||||
})
|
||||
|
||||
// 获取指定字段
|
||||
user := db.Get("user", "id,name,email", common.Map{
|
||||
"status": 1,
|
||||
})
|
||||
```
|
||||
|
||||
### 插入(Insert)
|
||||
|
||||
```go
|
||||
// 基本插入
|
||||
id := db.Insert("user", common.Map{
|
||||
"name": "张三",
|
||||
"email": "zhangsan@example.com",
|
||||
"age": 25,
|
||||
"status": 1,
|
||||
"created_time[#]": "NOW()", // [#]表示直接插入SQL函数
|
||||
})
|
||||
|
||||
// 返回插入的ID
|
||||
fmt.Println("插入的用户ID:", id)
|
||||
```
|
||||
|
||||
### 更新(Update)
|
||||
|
||||
```go
|
||||
// 基本更新
|
||||
affected := db.Update("user", common.Map{
|
||||
"name": "李四",
|
||||
"email": "lisi@example.com",
|
||||
"updated_time[#]": "NOW()",
|
||||
}, common.Map{
|
||||
"id": 1,
|
||||
})
|
||||
|
||||
// 条件更新
|
||||
affected := db.Update("user", common.Map{
|
||||
"status": 0,
|
||||
}, common.Map{
|
||||
"age[<]": 18,
|
||||
"status": 1,
|
||||
})
|
||||
|
||||
fmt.Println("更新的记录数:", affected)
|
||||
```
|
||||
|
||||
### 删除(Delete)
|
||||
|
||||
```go
|
||||
// 根据ID删除
|
||||
affected := db.Delete("user", common.Map{
|
||||
"id": 1,
|
||||
})
|
||||
|
||||
// 条件删除
|
||||
affected := db.Delete("user", common.Map{
|
||||
"status": 0,
|
||||
"created_time[<]": "2023-01-01",
|
||||
})
|
||||
|
||||
fmt.Println("删除的记录数:", affected)
|
||||
```
|
||||
|
||||
## 链式查询构建器
|
||||
|
||||
HoTimeDB提供了链式查询构建器,让查询更加直观:
|
||||
|
||||
```go
|
||||
// 基本链式查询
|
||||
users := db.Table("user").
|
||||
Where("status", 1).
|
||||
And("age[>]", 18).
|
||||
Order("created_time DESC").
|
||||
Limit(10, 20). // offset, limit
|
||||
Select()
|
||||
|
||||
// 链式获取单条记录
|
||||
user := db.Table("user").
|
||||
Where("id", 1).
|
||||
Get()
|
||||
|
||||
// 链式更新
|
||||
affected := db.Table("user").
|
||||
Where("id", 1).
|
||||
Update(common.Map{
|
||||
"name": "新名称",
|
||||
"updated_time[#]": "NOW()",
|
||||
})
|
||||
|
||||
// 链式删除
|
||||
affected := db.Table("user").
|
||||
Where("status", 0).
|
||||
Delete()
|
||||
|
||||
// 链式统计
|
||||
count := db.Table("user").
|
||||
Where("status", 1).
|
||||
Count()
|
||||
```
|
||||
|
||||
### 链式条件组合
|
||||
|
||||
```go
|
||||
// 复杂条件组合
|
||||
users := db.Table("user").
|
||||
Where("status", 1).
|
||||
And("age[>=]", 18).
|
||||
Or(common.Map{
|
||||
"level[>]": 5,
|
||||
"vip": 1,
|
||||
}).
|
||||
Order("created_time DESC", "id ASC").
|
||||
Group("department").
|
||||
Limit(0, 20).
|
||||
Select("id,name,email,age")
|
||||
```
|
||||
|
||||
## 条件查询语法
|
||||
|
||||
HoTimeDB支持丰富的条件查询语法,类似于Medoo:
|
||||
|
||||
### 基本比较
|
||||
|
||||
```go
|
||||
// 等于
|
||||
"id": 1
|
||||
|
||||
// 不等于
|
||||
"id[!]": 1
|
||||
|
||||
// 大于
|
||||
"age[>]": 18
|
||||
|
||||
// 大于等于
|
||||
"age[>=]": 18
|
||||
|
||||
// 小于
|
||||
"age[<]": 60
|
||||
|
||||
// 小于等于
|
||||
"age[<=]": 60
|
||||
```
|
||||
|
||||
### 模糊查询
|
||||
|
||||
```go
|
||||
// LIKE %keyword%
|
||||
"name[~]": "张"
|
||||
|
||||
// LIKE keyword% (右边任意)
|
||||
"name[~!]": "张"
|
||||
|
||||
// LIKE %keyword (左边任意)
|
||||
"name[!~]": "san"
|
||||
|
||||
// 手动LIKE(需要手动添加%)
|
||||
"name[~~]": "%张%"
|
||||
```
|
||||
|
||||
### 区间查询
|
||||
|
||||
```go
|
||||
// BETWEEN
|
||||
"age[<>]": []int{18, 60}
|
||||
|
||||
// NOT BETWEEN
|
||||
"age[><]": []int{18, 25}
|
||||
```
|
||||
|
||||
### IN查询
|
||||
|
||||
```go
|
||||
// IN
|
||||
"id": []int{1, 2, 3, 4, 5}
|
||||
|
||||
// NOT IN
|
||||
"id[!]": []int{1, 2, 3}
|
||||
```
|
||||
|
||||
### NULL查询
|
||||
|
||||
```go
|
||||
// IS NULL
|
||||
"deleted_at": nil
|
||||
|
||||
// IS NOT NULL
|
||||
"deleted_at[!]": nil
|
||||
```
|
||||
|
||||
### 直接SQL
|
||||
|
||||
```go
|
||||
// 直接插入SQL表达式(注意防注入)
|
||||
"created_time[#]": "> DATE_SUB(NOW(), INTERVAL 1 DAY)"
|
||||
|
||||
// 字段直接赋值(不使用参数化查询)
|
||||
"update_time[#]": "NOW()"
|
||||
|
||||
// 直接SQL片段
|
||||
"[##]": "user.status = 1 AND user.level > 0"
|
||||
```
|
||||
|
||||
## JOIN操作
|
||||
|
||||
### 链式JOIN
|
||||
|
||||
```go
|
||||
// LEFT JOIN
|
||||
users := db.Table("user").
|
||||
LeftJoin("profile", "user.id = profile.user_id").
|
||||
LeftJoin("department", "user.dept_id = department.id").
|
||||
Where("user.status", 1).
|
||||
Select("user.*, profile.avatar, department.name AS dept_name")
|
||||
|
||||
// RIGHT JOIN
|
||||
users := db.Table("user").
|
||||
RightJoin("order", "user.id = order.user_id").
|
||||
Select()
|
||||
|
||||
// INNER JOIN
|
||||
users := db.Table("user").
|
||||
InnerJoin("profile", "user.id = profile.user_id").
|
||||
Select()
|
||||
|
||||
// FULL JOIN
|
||||
users := db.Table("user").
|
||||
FullJoin("profile", "user.id = profile.user_id").
|
||||
Select()
|
||||
```
|
||||
|
||||
### 传统JOIN语法
|
||||
|
||||
```go
|
||||
users := db.Select("user",
|
||||
common.Slice{
|
||||
common.Map{"[>]profile": "user.id = profile.user_id"},
|
||||
common.Map{"[>]department": "user.dept_id = department.id"},
|
||||
},
|
||||
"user.*, profile.avatar, department.name AS dept_name",
|
||||
common.Map{
|
||||
"user.status": 1,
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
### JOIN类型说明
|
||||
|
||||
- `[>]`: LEFT JOIN
|
||||
- `[<]`: RIGHT JOIN
|
||||
- `[><]`: INNER JOIN
|
||||
- `[<>]`: FULL JOIN
|
||||
|
||||
## 分页查询
|
||||
|
||||
### 基本分页
|
||||
|
||||
```go
|
||||
// 设置分页:页码3,每页20条
|
||||
users := db.Page(3, 20).PageSelect("user", "*", common.Map{
|
||||
"status": 1,
|
||||
})
|
||||
|
||||
// 链式分页
|
||||
users := db.Table("user").
|
||||
Where("status", 1).
|
||||
Page(2, 15). // 第2页,每页15条
|
||||
Select()
|
||||
```
|
||||
|
||||
### 分页信息获取
|
||||
|
||||
```go
|
||||
// 获取总数
|
||||
total := db.Count("user", common.Map{
|
||||
"status": 1,
|
||||
})
|
||||
|
||||
// 计算分页信息
|
||||
page := 2
|
||||
pageSize := 20
|
||||
offset := (page - 1) * pageSize
|
||||
totalPages := (total + pageSize - 1) / pageSize
|
||||
|
||||
fmt.Printf("总记录数: %d, 总页数: %d, 当前页: %d\n", total, totalPages, page)
|
||||
```
|
||||
|
||||
## 聚合函数
|
||||
|
||||
### 计数
|
||||
|
||||
```go
|
||||
// 总数统计
|
||||
total := db.Count("user")
|
||||
|
||||
// 条件统计
|
||||
activeUsers := db.Count("user", common.Map{
|
||||
"status": 1,
|
||||
})
|
||||
|
||||
// JOIN统计
|
||||
count := db.Count("user",
|
||||
common.Slice{
|
||||
common.Map{"[>]profile": "user.id = profile.user_id"},
|
||||
},
|
||||
common.Map{
|
||||
"user.status": 1,
|
||||
"profile.verified": 1,
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
### 求和
|
||||
|
||||
```go
|
||||
// 基本求和
|
||||
totalAmount := db.Sum("order", "amount")
|
||||
|
||||
// 条件求和
|
||||
paidAmount := db.Sum("order", "amount", common.Map{
|
||||
"status": "paid",
|
||||
"created_time[>]": "2023-01-01",
|
||||
})
|
||||
|
||||
// JOIN求和
|
||||
sum := db.Sum("order", "amount",
|
||||
common.Slice{
|
||||
common.Map{"[>]user": "order.user_id = user.id"},
|
||||
},
|
||||
common.Map{
|
||||
"user.level": "vip",
|
||||
"order.status": "paid",
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
## 事务处理
|
||||
|
||||
```go
|
||||
// 事务操作
|
||||
success := db.Action(func(tx db.HoTimeDB) bool {
|
||||
// 在事务中执行多个操作
|
||||
|
||||
// 扣减用户余额
|
||||
affected1 := tx.Update("user", common.Map{
|
||||
"balance[#]": "balance - 100",
|
||||
}, common.Map{
|
||||
"id": 1,
|
||||
})
|
||||
|
||||
if affected1 == 0 {
|
||||
return false // 回滚
|
||||
}
|
||||
|
||||
// 创建订单
|
||||
orderId := tx.Insert("order", common.Map{
|
||||
"user_id": 1,
|
||||
"amount": 100,
|
||||
"status": "paid",
|
||||
"created_time[#]": "NOW()",
|
||||
})
|
||||
|
||||
if orderId == 0 {
|
||||
return false // 回滚
|
||||
}
|
||||
|
||||
// 添加订单详情
|
||||
detailId := tx.Insert("order_detail", common.Map{
|
||||
"order_id": orderId,
|
||||
"product_id": 1001,
|
||||
"quantity": 1,
|
||||
"price": 100,
|
||||
})
|
||||
|
||||
if detailId == 0 {
|
||||
return false // 回滚
|
||||
}
|
||||
|
||||
return true // 提交
|
||||
})
|
||||
|
||||
if success {
|
||||
fmt.Println("事务执行成功")
|
||||
} else {
|
||||
fmt.Println("事务回滚")
|
||||
fmt.Println("错误:", db.LastErr.GetError())
|
||||
}
|
||||
```
|
||||
|
||||
## 缓存机制
|
||||
|
||||
HoTimeDB集成了缓存功能,可以自动缓存查询结果:
|
||||
|
||||
### 缓存配置
|
||||
|
||||
```go
|
||||
import "code.hoteas.com/golang/hotime/cache"
|
||||
|
||||
// 设置缓存
|
||||
db.HoTimeCache = &cache.HoTimeCache{
|
||||
// 缓存配置
|
||||
}
|
||||
```
|
||||
|
||||
### 缓存行为
|
||||
|
||||
- 查询操作会自动检查缓存
|
||||
- 增删改操作会自动清除相关缓存
|
||||
- 缓存键格式:`表名:查询MD5`
|
||||
- `cached`表不会被缓存
|
||||
|
||||
### 缓存清理
|
||||
|
||||
```go
|
||||
// 手动清除表缓存
|
||||
db.HoTimeCache.Db("user*", nil) // 清除user表所有缓存
|
||||
```
|
||||
|
||||
## 高级特性
|
||||
|
||||
### 调试模式
|
||||
|
||||
```go
|
||||
// 设置调试模式
|
||||
db.Mode = 2
|
||||
|
||||
// 查看最后执行的SQL
|
||||
fmt.Println("最后的SQL:", db.LastQuery)
|
||||
fmt.Println("参数:", db.LastData)
|
||||
fmt.Println("错误:", db.LastErr.GetError())
|
||||
```
|
||||
|
||||
### 主从分离
|
||||
|
||||
```go
|
||||
func createConnection() (master, slave *sql.DB) {
|
||||
// 主库连接
|
||||
master, _ = sql.Open("mysql", "user:password@tcp(master:3306)/database")
|
||||
|
||||
// 从库连接
|
||||
slave, _ = sql.Open("mysql", "user:password@tcp(slave:3306)/database")
|
||||
|
||||
return master, slave
|
||||
}
|
||||
|
||||
db.SetConnect(createConnection)
|
||||
// 查询会自动使用从库,增删改使用主库
|
||||
```
|
||||
|
||||
### 原生SQL执行
|
||||
|
||||
```go
|
||||
// 执行查询SQL
|
||||
results := db.Query("SELECT * FROM user WHERE age > ? AND status = ?", 18, 1)
|
||||
|
||||
// 执行更新SQL
|
||||
result, err := db.Exec("UPDATE user SET last_login = NOW() WHERE id = ?", 1)
|
||||
if err.GetError() == nil {
|
||||
affected, _ := result.RowsAffected()
|
||||
fmt.Println("影响行数:", affected)
|
||||
}
|
||||
```
|
||||
|
||||
### 数据类型处理
|
||||
|
||||
```go
|
||||
// 时间戳插入
|
||||
db.Insert("log", common.Map{
|
||||
"user_id": 1,
|
||||
"action": "login",
|
||||
"created_time[#]": "UNIX_TIMESTAMP()",
|
||||
})
|
||||
|
||||
// JSON数据
|
||||
db.Insert("user", common.Map{
|
||||
"name": "张三",
|
||||
"preferences": `{"theme": "dark", "language": "zh-CN"}`,
|
||||
})
|
||||
```
|
||||
|
||||
### 数据行处理
|
||||
|
||||
HoTimeDB内部的`Row`方法会自动处理不同数据类型:
|
||||
|
||||
```go
|
||||
// 自动转换[]uint8为字符串
|
||||
// 保持其他类型的原始值
|
||||
// 处理NULL值
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
```go
|
||||
// 检查错误
|
||||
users := db.Select("user", "*", common.Map{"status": 1})
|
||||
if db.LastErr.GetError() != nil {
|
||||
fmt.Println("查询错误:", db.LastErr.GetError())
|
||||
return
|
||||
}
|
||||
|
||||
// 插入时检查错误
|
||||
id := db.Insert("user", common.Map{
|
||||
"name": "test",
|
||||
"email": "test@example.com",
|
||||
})
|
||||
|
||||
if id == 0 && db.LastErr.GetError() != nil {
|
||||
fmt.Println("插入失败:", db.LastErr.GetError())
|
||||
}
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### IN查询优化
|
||||
|
||||
HoTimeDB会自动优化IN查询,将连续的数字转换为BETWEEN查询以提高性能:
|
||||
|
||||
```go
|
||||
// 这个查询会被自动优化(单个IN条件)
|
||||
users := db.Select("user", "*", common.Map{
|
||||
"id": []int{1, 2, 3, 4, 5, 10, 11, 12},
|
||||
// 自动转为 (id BETWEEN 1 AND 5) OR (id BETWEEN 10 AND 12)
|
||||
})
|
||||
```
|
||||
|
||||
### 批量操作
|
||||
|
||||
```go
|
||||
// 使用事务进行批量插入
|
||||
success := db.Action(func(tx db.HoTimeDB) bool {
|
||||
for i := 0; i < 1000; i++ {
|
||||
id := tx.Insert("user", common.Map{
|
||||
"name": fmt.Sprintf("User%d", i),
|
||||
"email": fmt.Sprintf("user%d@example.com", i),
|
||||
"created_time[#]": "NOW()",
|
||||
})
|
||||
if id == 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
```
|
||||
|
||||
## 特殊语法详解
|
||||
|
||||
### 条件标记符说明
|
||||
|
||||
| 标记符 | 功能 | 示例 | 生成SQL |
|
||||
|--------|------|------|---------|
|
||||
| `[>]` | 大于 | `"age[>]": 18` | `age > 18` |
|
||||
| `[<]` | 小于 | `"age[<]": 60` | `age < 60` |
|
||||
| `[>=]` | 大于等于 | `"age[>=]": 18` | `age >= 18` |
|
||||
| `[<=]` | 小于等于 | `"age[<=]": 60` | `age <= 60` |
|
||||
| `[!]` | 不等于/NOT IN | `"id[!]": 1` | `id != 1` |
|
||||
| `[~]` | LIKE模糊查询 | `"name[~]": "张"` | `name LIKE '%张%'` |
|
||||
| `[!~]` | 左模糊 | `"name[!~]": "张"` | `name LIKE '%张'` |
|
||||
| `[~!]` | 右模糊 | `"name[~!]": "张"` | `name LIKE '张%'` |
|
||||
| `[~~]` | 手动LIKE | `"name[~~]": "%张%"` | `name LIKE '%张%'` |
|
||||
| `[<>]` | BETWEEN | `"age[<>]": [18,60]` | `age BETWEEN 18 AND 60` |
|
||||
| `[><]` | NOT BETWEEN | `"age[><]": [18,25]` | `age NOT BETWEEN 18 AND 25` |
|
||||
| `[#]` | 直接SQL | `"time[#]": "NOW()"` | `time = NOW()` |
|
||||
| `[##]` | SQL片段 | `"[##]": "a > b"` | `a > b` |
|
||||
| `[#!]` | 不等于直接SQL | `"status[#!]": "1"` | `status != 1` |
|
||||
| `[!#]` | 不等于直接SQL | `"status[!#]": "1"` | `status != 1` |
|
||||
|
||||
## 与PHP Medoo的差异
|
||||
|
||||
1. **类型系统**: Golang的强类型要求使用`common.Map`和`common.Slice`
|
||||
2. **语法差异**: 某些条件语法可能略有不同
|
||||
3. **错误处理**: 使用Golang的错误处理模式
|
||||
4. **并发安全**: 需要注意并发使用时的安全性
|
||||
5. **缓存集成**: 内置了缓存功能
|
||||
6. **链式调用**: 提供了更丰富的链式API
|
||||
|
||||
## 完整示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"database/sql"
|
||||
"code.hoteas.com/golang/hotime/db"
|
||||
"code.hoteas.com/golang/hotime/common"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 初始化数据库
|
||||
database := &db.HoTimeDB{
|
||||
Prefix: "app_",
|
||||
Mode: 2, // 开发模式
|
||||
}
|
||||
|
||||
database.SetConnect(func(err ...*common.Error) (master, slave *sql.DB) {
|
||||
master, _ = sql.Open("mysql", "root:password@tcp(localhost:3306)/testdb")
|
||||
return master, master
|
||||
})
|
||||
|
||||
// 查询用户列表
|
||||
users := database.Table("user").
|
||||
Where("status", 1).
|
||||
And("age[>=]", 18).
|
||||
Order("created_time DESC").
|
||||
Limit(0, 10).
|
||||
Select("id,name,email,age")
|
||||
|
||||
for _, user := range users {
|
||||
fmt.Printf("用户: %s, 邮箱: %s, 年龄: %v\n",
|
||||
user.GetString("name"),
|
||||
user.GetString("email"),
|
||||
user.Get("age"))
|
||||
}
|
||||
|
||||
// 创建新用户
|
||||
userId := database.Insert("user", common.Map{
|
||||
"name": "新用户",
|
||||
"email": "new@example.com",
|
||||
"age": 25,
|
||||
"status": 1,
|
||||
"created_time[#]": "NOW()",
|
||||
})
|
||||
|
||||
fmt.Printf("创建用户ID: %d\n", userId)
|
||||
|
||||
// 更新用户
|
||||
affected := database.Table("user").
|
||||
Where("id", userId).
|
||||
Update(common.Map{
|
||||
"last_login[#]": "NOW()",
|
||||
"login_count[#]": "login_count + 1",
|
||||
})
|
||||
|
||||
fmt.Printf("更新记录数: %d\n", affected)
|
||||
|
||||
// 复杂查询示例
|
||||
orders := database.Table("order").
|
||||
LeftJoin("user", "order.user_id = user.id").
|
||||
LeftJoin("product", "order.product_id = product.id").
|
||||
Where("order.status", "paid").
|
||||
And("order.created_time[>]", "2023-01-01").
|
||||
And(common.Map{
|
||||
"OR": common.Map{
|
||||
"user.level": "vip",
|
||||
"order.amount[>]": 1000,
|
||||
},
|
||||
}).
|
||||
Order("order.created_time DESC").
|
||||
Group("user.id").
|
||||
Select("user.name, user.email, SUM(order.amount) as total_amount, COUNT(*) as order_count")
|
||||
|
||||
// 事务示例
|
||||
success := database.Action(func(tx db.HoTimeDB) bool {
|
||||
// 在事务中执行操作
|
||||
orderId := tx.Insert("order", common.Map{
|
||||
"user_id": userId,
|
||||
"total": 100.50,
|
||||
"status": "pending",
|
||||
"created_time[#]": "NOW()",
|
||||
})
|
||||
|
||||
if orderId == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
detailId := tx.Insert("order_detail", common.Map{
|
||||
"order_id": orderId,
|
||||
"product_id": 1,
|
||||
"quantity": 2,
|
||||
"price": 50.25,
|
||||
})
|
||||
|
||||
return detailId > 0
|
||||
})
|
||||
|
||||
if success {
|
||||
fmt.Println("订单创建成功")
|
||||
} else {
|
||||
fmt.Println("订单创建失败:", database.LastErr.GetError())
|
||||
}
|
||||
|
||||
// 统计示例
|
||||
totalUsers := database.Count("user", common.Map{"status": 1})
|
||||
totalAmount := database.Sum("order", "amount", common.Map{"status": "paid"})
|
||||
|
||||
fmt.Printf("活跃用户数: %d, 总交易额: %.2f\n", totalUsers, totalAmount)
|
||||
}
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q1: 如何处理事务中的错误?
|
||||
A1: 在`Action`函数中返回`false`即可触发回滚,所有操作都会被撤销。
|
||||
|
||||
### Q2: 缓存何时会被清除?
|
||||
A2: 执行`Insert`、`Update`、`Delete`操作时会自动清除对应表的缓存。
|
||||
|
||||
### Q3: 如何执行复杂的原生SQL?
|
||||
A3: 使用`Query`方法执行查询,使用`Exec`方法执行更新操作。
|
||||
|
||||
### Q4: 主从分离如何工作?
|
||||
A4: 查询操作自动使用从库(如果配置了),增删改操作使用主库。
|
||||
|
||||
### Q5: 如何处理NULL值?
|
||||
A5: 使用`nil`作为值,查询时使用`"field": nil`表示`IS NULL`。
|
||||
|
||||
---
|
||||
|
||||
*文档版本: 1.0*
|
||||
*最后更新: 2024年*
|
||||
|
||||
> 本文档基于HoTimeDB源码分析生成,如有疑问请参考源码实现。该ORM框架参考了PHP Medoo的设计理念,但根据Golang语言特性进行了适配和优化。
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
# HoTimeDB ORM 文档集合
|
||||
|
||||
这是HoTimeDB ORM框架的完整文档集合,包含使用说明、API参考、示例代码和测试数据。
|
||||
|
||||
## ⚠️ 重要更新说明
|
||||
|
||||
**语法修正通知**:经过对源码的深入分析,发现HoTimeDB的条件查询语法有特定规则:
|
||||
- ✅ **单个条件**:可以直接写在Map中
|
||||
- ⚠️ **多个条件**:必须使用`AND`或`OR`包装
|
||||
- 📝 所有文档和示例代码已按正确语法更新
|
||||
|
||||
## 📚 文档列表
|
||||
|
||||
### 1. [HoTimeDB_使用说明.md](./HoTimeDB_使用说明.md)
|
||||
**完整使用说明书** - 详细的功能介绍和使用指南
|
||||
- 🚀 快速开始
|
||||
- ⚙️ 数据库配置
|
||||
- 🔧 基本操作 (CRUD)
|
||||
- 🔗 链式查询构建器
|
||||
- 🔍 条件查询语法
|
||||
- 🔄 JOIN操作
|
||||
- 📄 分页查询
|
||||
- 📊 聚合函数
|
||||
- 🔐 事务处理
|
||||
- 💾 缓存机制
|
||||
- ⚡ 高级特性
|
||||
|
||||
### 2. [HoTimeDB_API参考.md](./HoTimeDB_API参考.md)
|
||||
**快速API参考手册** - 开发时的速查手册
|
||||
- 📖 基本方法
|
||||
- 🔧 CRUD操作
|
||||
- 📊 聚合函数
|
||||
- 📄 分页查询
|
||||
- 🔍 条件语法参考
|
||||
- 🔗 JOIN语法
|
||||
- 🔐 事务处理
|
||||
- 🛠️ 工具方法
|
||||
|
||||
### 3. [示例代码文件](../examples/hotimedb_examples.go)
|
||||
**完整示例代码集合** - 可运行的实际应用示例(语法已修正)
|
||||
- 🏗️ 基本初始化和配置
|
||||
- 📝 基本CRUD操作
|
||||
- 🔗 链式查询操作
|
||||
- 🤝 JOIN查询操作
|
||||
- 🔍 条件查询语法
|
||||
- 📄 分页查询
|
||||
- 📊 聚合函数查询
|
||||
- 🔐 事务处理
|
||||
- 💾 缓存机制
|
||||
- 🔧 原生SQL执行
|
||||
- 🚨 错误处理和调试
|
||||
- ⚡ 性能优化技巧
|
||||
- 🎯 完整应用示例
|
||||
|
||||
### 4. [test_tables.sql](./test_tables.sql)
|
||||
**测试数据库结构** - 快速搭建测试环境
|
||||
- 🏗️ 完整的表结构定义
|
||||
- 📊 测试数据插入
|
||||
- 🔍 索引优化
|
||||
- 👁️ 视图示例
|
||||
- 🔧 存储过程示例
|
||||
|
||||
## 🎯 核心特性
|
||||
|
||||
### 🌟 主要优势
|
||||
- **类Medoo语法**: 参考PHP Medoo设计,语法简洁易懂
|
||||
- **链式查询**: 支持流畅的链式查询构建器
|
||||
- **条件丰富**: 支持丰富的条件查询语法
|
||||
- **事务支持**: 完整的事务处理机制
|
||||
- **缓存集成**: 内置查询结果缓存
|
||||
- **读写分离**: 支持主从数据库配置
|
||||
- **类型安全**: 基于Golang的强类型系统
|
||||
|
||||
### 🔧 支持的数据库
|
||||
- ✅ MySQL
|
||||
- ✅ SQLite
|
||||
- ✅ 其他标准SQL数据库
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 1. 安装依赖
|
||||
```bash
|
||||
go mod init your-project
|
||||
go get github.com/go-sql-driver/mysql
|
||||
go get github.com/sirupsen/logrus
|
||||
```
|
||||
|
||||
### 2. 创建测试数据库
|
||||
```bash
|
||||
mysql -u root -p < test_tables.sql
|
||||
```
|
||||
|
||||
### 3. 基本使用
|
||||
```go
|
||||
import (
|
||||
"code.hoteas.com/golang/hotime/db"
|
||||
"code.hoteas.com/golang/hotime/common"
|
||||
"database/sql"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
// 初始化数据库
|
||||
database := &db.HoTimeDB{
|
||||
Prefix: "app_",
|
||||
Mode: 2, // 开发模式
|
||||
}
|
||||
|
||||
database.SetConnect(func() (master, slave *sql.DB) {
|
||||
master, _ = sql.Open("mysql", "user:pass@tcp(localhost:3306)/dbname")
|
||||
return master, master
|
||||
})
|
||||
|
||||
// 链式查询(链式语法支持单独Where然后用And添加条件)
|
||||
users := database.Table("user").
|
||||
Where("status", 1). // 链式中可以单独Where
|
||||
And("age[>]", 18). // 用And添加更多条件
|
||||
Order("created_time DESC").
|
||||
Limit(0, 10).
|
||||
Select("id,name,email")
|
||||
|
||||
// 或者使用传统语法(多个条件必须用AND包装)
|
||||
users2 := database.Select("user", "id,name,email", common.Map{
|
||||
"AND": common.Map{
|
||||
"status": 1,
|
||||
"age[>]": 18,
|
||||
},
|
||||
"ORDER": "created_time DESC",
|
||||
"LIMIT": []int{0, 10},
|
||||
})
|
||||
```
|
||||
|
||||
## ⚠️ 重要语法规则
|
||||
|
||||
**条件查询语法规则:**
|
||||
- ✅ **单个条件**:可以直接写在Map中
|
||||
- ✅ **多个条件**:必须使用`AND`或`OR`包装
|
||||
- ✅ **特殊参数**:`ORDER`、`GROUP`、`LIMIT`与条件同级
|
||||
|
||||
```go
|
||||
// ✅ 正确:单个条件
|
||||
Map{"status": 1}
|
||||
|
||||
// ✅ 正确:多个条件用AND包装
|
||||
Map{
|
||||
"AND": Map{
|
||||
"status": 1,
|
||||
"age[>]": 18,
|
||||
},
|
||||
"ORDER": "id DESC",
|
||||
}
|
||||
|
||||
// ❌ 错误:多个条件不用AND包装
|
||||
Map{
|
||||
"status": 1,
|
||||
"age[>]": 18, // 不支持!
|
||||
}
|
||||
```
|
||||
|
||||
## 📝 条件查询语法速查
|
||||
|
||||
| 语法 | SQL | 说明 |
|
||||
|------|-----|------|
|
||||
| `"field": value` | `field = ?` | 等于 |
|
||||
| `"field[!]": value` | `field != ?` | 不等于 |
|
||||
| `"field[>]": value` | `field > ?` | 大于 |
|
||||
| `"field[>=]": value` | `field >= ?` | 大于等于 |
|
||||
| `"field[<]": value` | `field < ?` | 小于 |
|
||||
| `"field[<=]": value` | `field <= ?` | 小于等于 |
|
||||
| `"field[~]": "keyword"` | `field LIKE '%keyword%'` | 包含 |
|
||||
| `"field[<>]": [min, max]` | `field BETWEEN ? AND ?` | 区间内 |
|
||||
| `"field": [v1, v2, v3]` | `field IN (?, ?, ?)` | 在集合中 |
|
||||
| `"field": nil` | `field IS NULL` | 为空 |
|
||||
| `"field[#]": "NOW()"` | `field = NOW()` | 直接SQL |
|
||||
|
||||
## 🔗 JOIN语法速查
|
||||
|
||||
| 语法 | SQL | 说明 |
|
||||
|------|-----|------|
|
||||
| `"[>]table"` | `LEFT JOIN` | 左连接 |
|
||||
| `"[<]table"` | `RIGHT JOIN` | 右连接 |
|
||||
| `"[><]table"` | `INNER JOIN` | 内连接 |
|
||||
| `"[<>]table"` | `FULL JOIN` | 全连接 |
|
||||
|
||||
## 🛠️ 链式方法速查
|
||||
|
||||
```go
|
||||
db.Table("table") // 指定表名
|
||||
.Where(key, value) // WHERE条件
|
||||
.And(key, value) // AND条件
|
||||
.Or(map) // OR条件
|
||||
.LeftJoin(table, on) // LEFT JOIN
|
||||
.Order(fields...) // ORDER BY
|
||||
.Group(fields...) // GROUP BY
|
||||
.Limit(offset, limit) // LIMIT
|
||||
.Page(page, pageSize) // 分页
|
||||
.Select(fields...) // 查询
|
||||
.Get(fields...) // 获取单条
|
||||
.Count() // 计数
|
||||
.Update(data) // 更新
|
||||
.Delete() // 删除
|
||||
```
|
||||
|
||||
## ⚡ 性能优化建议
|
||||
|
||||
### 🔍 查询优化
|
||||
- 使用合适的索引字段作为查询条件
|
||||
- IN查询会自动优化为BETWEEN(连续数字)
|
||||
- 避免SELECT *,指定需要的字段
|
||||
- 合理使用LIMIT限制结果集大小
|
||||
|
||||
### 💾 缓存使用
|
||||
- 查询结果会自动缓存
|
||||
- 增删改操作会自动清除缓存
|
||||
- `cached`表不参与缓存
|
||||
|
||||
### 🔐 事务处理
|
||||
- 批量操作使用事务提高性能
|
||||
- 事务中避免长时间操作
|
||||
- 合理设置事务隔离级别
|
||||
|
||||
## 🚨 注意事项
|
||||
|
||||
### 🔒 安全相关
|
||||
- 使用参数化查询防止SQL注入
|
||||
- `[#]`语法需要注意防止注入
|
||||
- 敏感数据加密存储
|
||||
|
||||
### 🎯 最佳实践
|
||||
- 开发时设置`Mode = 2`便于调试
|
||||
- 生产环境设置`Mode = 0`
|
||||
- 合理设置表前缀
|
||||
- 定期检查慢查询日志
|
||||
|
||||
## 🤝 与PHP Medoo的差异
|
||||
|
||||
1. **类型系统**: 使用`common.Map`和`common.Slice`
|
||||
2. **错误处理**: Golang风格的错误处理
|
||||
3. **链式调用**: 提供更丰富的链式API
|
||||
4. **缓存集成**: 内置缓存功能
|
||||
5. **并发安全**: 需要注意并发使用
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
- 📧 查看源码:`hotimedb.go`
|
||||
- 📖 参考文档:本目录下的各个文档文件
|
||||
- 🔧 示例代码:运行`HoTimeDB_示例代码.go`中的示例
|
||||
|
||||
---
|
||||
|
||||
**HoTimeDB ORM框架 - 让数据库操作更简单!** 🎉
|
||||
|
||||
> 本文档基于HoTimeDB源码分析生成,参考了PHP Medoo的设计理念,并根据Golang语言特性进行了优化。
|
||||
@@ -0,0 +1,332 @@
|
||||
-- HoTimeDB 测试表结构
|
||||
-- 用于测试和示例的MySQL表结构定义
|
||||
-- 请根据实际需要修改表结构和字段类型
|
||||
|
||||
-- 创建数据库(可选)
|
||||
CREATE DATABASE IF NOT EXISTS `hotimedb_test` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
USE `hotimedb_test`;
|
||||
|
||||
-- 用户表
|
||||
DROP TABLE IF EXISTS `app_user`;
|
||||
CREATE TABLE `app_user` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',
|
||||
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '用户姓名',
|
||||
`email` varchar(255) NOT NULL DEFAULT '' COMMENT '邮箱地址',
|
||||
`password` varchar(255) NOT NULL DEFAULT '' COMMENT '密码hash',
|
||||
`phone` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号',
|
||||
`age` int(11) NOT NULL DEFAULT '0' COMMENT '年龄',
|
||||
`gender` tinyint(4) NOT NULL DEFAULT '0' COMMENT '性别 0-未知 1-男 2-女',
|
||||
`avatar` varchar(500) NOT NULL DEFAULT '' COMMENT '头像URL',
|
||||
`level` varchar(20) NOT NULL DEFAULT 'normal' COMMENT '用户等级 normal-普通 vip-会员 svip-超级会员',
|
||||
`balance` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '账户余额',
|
||||
`login_count` int(11) NOT NULL DEFAULT '0' COMMENT '登录次数',
|
||||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态 1-正常 0-禁用 -1-删除',
|
||||
`last_login` datetime DEFAULT NULL COMMENT '最后登录时间',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_email` (`email`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_level` (`level`),
|
||||
KEY `idx_created_time` (`created_time`),
|
||||
KEY `idx_deleted_at` (`deleted_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
|
||||
|
||||
-- 用户资料表
|
||||
DROP TABLE IF EXISTS `app_profile`;
|
||||
CREATE TABLE `app_profile` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID',
|
||||
`real_name` varchar(50) NOT NULL DEFAULT '' COMMENT '真实姓名',
|
||||
`id_card` varchar(20) NOT NULL DEFAULT '' COMMENT '身份证号',
|
||||
`address` varchar(500) NOT NULL DEFAULT '' COMMENT '地址',
|
||||
`bio` text COMMENT '个人简介',
|
||||
`verified` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否认证 1-是 0-否',
|
||||
`preferences` json DEFAULT NULL COMMENT '用户偏好设置JSON',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_user_id` (`user_id`),
|
||||
KEY `idx_verified` (`verified`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户资料表';
|
||||
|
||||
-- 部门表
|
||||
DROP TABLE IF EXISTS `app_department`;
|
||||
CREATE TABLE `app_department` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '部门ID',
|
||||
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '部门名称',
|
||||
`parent_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '上级部门ID',
|
||||
`manager_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '部门经理ID',
|
||||
`description` text COMMENT '部门描述',
|
||||
`sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',
|
||||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态 1-正常 0-禁用',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_parent_id` (`parent_id`),
|
||||
KEY `idx_manager_id` (`manager_id`),
|
||||
KEY `idx_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='部门表';
|
||||
|
||||
-- 商品表
|
||||
DROP TABLE IF EXISTS `app_product`;
|
||||
CREATE TABLE `app_product` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '商品ID',
|
||||
`title` varchar(200) NOT NULL DEFAULT '' COMMENT '商品标题',
|
||||
`description` text COMMENT '商品描述',
|
||||
`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品价格',
|
||||
`stock` int(11) NOT NULL DEFAULT '0' COMMENT '库存数量',
|
||||
`category_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '分类ID',
|
||||
`brand` varchar(100) NOT NULL DEFAULT '' COMMENT '品牌',
|
||||
`tags` varchar(500) NOT NULL DEFAULT '' COMMENT '标签,逗号分隔',
|
||||
`images` json DEFAULT NULL COMMENT '商品图片JSON数组',
|
||||
`attributes` json DEFAULT NULL COMMENT '商品属性JSON',
|
||||
`sales_count` int(11) NOT NULL DEFAULT '0' COMMENT '销售数量',
|
||||
`view_count` int(11) NOT NULL DEFAULT '0' COMMENT '浏览数量',
|
||||
`sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',
|
||||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态 1-上架 0-下架',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_category_id` (`category_id`),
|
||||
KEY `idx_price` (`price`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_created_time` (`created_time`),
|
||||
FULLTEXT KEY `ft_title_description` (`title`,`description`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商品表';
|
||||
|
||||
-- 订单表
|
||||
DROP TABLE IF EXISTS `app_order`;
|
||||
CREATE TABLE `app_order` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '订单ID',
|
||||
`order_no` varchar(50) NOT NULL DEFAULT '' COMMENT '订单号',
|
||||
`user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID',
|
||||
`product_id` bigint(20) unsigned NOT NULL COMMENT '商品ID',
|
||||
`quantity` int(11) NOT NULL DEFAULT '1' COMMENT '数量',
|
||||
`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '单价',
|
||||
`amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '总金额',
|
||||
`discount_amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '优惠金额',
|
||||
`final_amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '实付金额',
|
||||
`status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '订单状态 pending-待付款 paid-已付款 shipped-已发货 completed-已完成 cancelled-已取消',
|
||||
`payment_method` varchar(20) NOT NULL DEFAULT '' COMMENT '支付方式',
|
||||
`shipping_address` json DEFAULT NULL COMMENT '收货地址JSON',
|
||||
`remark` text COMMENT '订单备注',
|
||||
`paid_time` datetime DEFAULT NULL COMMENT '支付时间',
|
||||
`shipped_time` datetime DEFAULT NULL COMMENT '发货时间',
|
||||
`completed_time` datetime DEFAULT NULL COMMENT '完成时间',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_order_no` (`order_no`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_product_id` (`product_id`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_created_time` (`created_time`),
|
||||
KEY `idx_paid_time` (`paid_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单表';
|
||||
|
||||
-- 订单详情表
|
||||
DROP TABLE IF EXISTS `app_order_detail`;
|
||||
CREATE TABLE `app_order_detail` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`order_id` bigint(20) unsigned NOT NULL COMMENT '订单ID',
|
||||
`product_id` bigint(20) unsigned NOT NULL COMMENT '商品ID',
|
||||
`product_title` varchar(200) NOT NULL DEFAULT '' COMMENT '商品标题',
|
||||
`product_image` varchar(500) NOT NULL DEFAULT '' COMMENT '商品图片',
|
||||
`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '单价',
|
||||
`quantity` int(11) NOT NULL DEFAULT '1' COMMENT '数量',
|
||||
`amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '小计',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_order_id` (`order_id`),
|
||||
KEY `idx_product_id` (`product_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单详情表';
|
||||
|
||||
-- 支付日志表
|
||||
DROP TABLE IF EXISTS `app_payment_log`;
|
||||
CREATE TABLE `app_payment_log` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID',
|
||||
`order_id` bigint(20) unsigned DEFAULT NULL COMMENT '订单ID',
|
||||
`transaction_id` varchar(100) NOT NULL DEFAULT '' COMMENT '交易ID',
|
||||
`type` varchar(20) NOT NULL DEFAULT '' COMMENT '类型 order_payment-订单支付 recharge-充值 refund-退款',
|
||||
`amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '金额',
|
||||
`method` varchar(20) NOT NULL DEFAULT '' COMMENT '支付方式 balance-余额 alipay-支付宝 wechat-微信',
|
||||
`status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '状态 pending-处理中 success-成功 failed-失败',
|
||||
`description` varchar(255) NOT NULL DEFAULT '' COMMENT '描述',
|
||||
`extra_data` json DEFAULT NULL COMMENT '额外数据JSON',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_order_id` (`order_id`),
|
||||
KEY `idx_transaction_id` (`transaction_id`),
|
||||
KEY `idx_type` (`type`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_created_time` (`created_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付日志表';
|
||||
|
||||
-- 转账日志表
|
||||
DROP TABLE IF EXISTS `app_transfer_log`;
|
||||
CREATE TABLE `app_transfer_log` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`from_user_id` bigint(20) unsigned NOT NULL COMMENT '转出用户ID',
|
||||
`to_user_id` bigint(20) unsigned NOT NULL COMMENT '转入用户ID',
|
||||
`amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '转账金额',
|
||||
`type` varchar(20) NOT NULL DEFAULT 'transfer' COMMENT '类型',
|
||||
`status` varchar(20) NOT NULL DEFAULT 'success' COMMENT '状态',
|
||||
`description` varchar(255) NOT NULL DEFAULT '' COMMENT '描述',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_from_user_id` (`from_user_id`),
|
||||
KEY `idx_to_user_id` (`to_user_id`),
|
||||
KEY `idx_created_time` (`created_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='转账日志表';
|
||||
|
||||
-- 操作日志表
|
||||
DROP TABLE IF EXISTS `app_operation_log`;
|
||||
CREATE TABLE `app_operation_log` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`user_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '用户ID',
|
||||
`module` varchar(50) NOT NULL DEFAULT '' COMMENT '模块',
|
||||
`action` varchar(50) NOT NULL DEFAULT '' COMMENT '操作',
|
||||
`description` varchar(255) NOT NULL DEFAULT '' COMMENT '描述',
|
||||
`ip` varchar(45) NOT NULL DEFAULT '' COMMENT 'IP地址',
|
||||
`user_agent` varchar(500) NOT NULL DEFAULT '' COMMENT '用户代理',
|
||||
`request_data` json DEFAULT NULL COMMENT '请求数据JSON',
|
||||
`response_data` json DEFAULT NULL COMMENT '响应数据JSON',
|
||||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态 1-成功 0-失败',
|
||||
`execution_time` int(11) NOT NULL DEFAULT '0' COMMENT '执行时间(毫秒)',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_module` (`module`),
|
||||
KEY `idx_action` (`action`),
|
||||
KEY `idx_created_time` (`created_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操作日志表';
|
||||
|
||||
-- 缓存表(HoTimeDB内置缓存使用)
|
||||
DROP TABLE IF EXISTS `app_cached`;
|
||||
CREATE TABLE `app_cached` (
|
||||
`key` varchar(255) NOT NULL COMMENT '缓存键',
|
||||
`value` longtext COMMENT '缓存值',
|
||||
`expire_time` datetime DEFAULT NULL COMMENT '过期时间',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`key`),
|
||||
KEY `idx_expire_time` (`expire_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='缓存表';
|
||||
|
||||
-- 批量用户表(用于批量操作示例)
|
||||
DROP TABLE IF EXISTS `app_user_batch`;
|
||||
CREATE TABLE `app_user_batch` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '用户姓名',
|
||||
`email` varchar(255) NOT NULL DEFAULT '' COMMENT '邮箱地址',
|
||||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态',
|
||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_created_time` (`created_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='批量用户表';
|
||||
|
||||
-- 插入测试数据
|
||||
INSERT INTO `app_user` (`name`, `email`, `password`, `age`, `level`, `balance`, `status`, `created_time`) VALUES
|
||||
('张三', 'zhangsan@example.com', 'hashed_password_1', 25, 'normal', 1000.00, 1, '2023-01-15 10:30:00'),
|
||||
('李四', 'lisi@example.com', 'hashed_password_2', 30, 'vip', 5000.00, 1, '2023-02-20 14:20:00'),
|
||||
('王五', 'wangwu@example.com', 'hashed_password_3', 28, 'svip', 10000.00, 1, '2023-03-10 16:45:00'),
|
||||
('赵六', 'zhaoliu@example.com', 'hashed_password_4', 35, 'normal', 500.00, 1, '2023-04-05 09:15:00'),
|
||||
('钱七', 'qianqi@example.com', 'hashed_password_5', 22, 'vip', 2500.00, 0, '2023-05-12 11:30:00');
|
||||
|
||||
INSERT INTO `app_profile` (`user_id`, `real_name`, `verified`) VALUES
|
||||
(1, '张三', 1),
|
||||
(2, '李四', 1),
|
||||
(3, '王五', 1),
|
||||
(4, '赵六', 0),
|
||||
(5, '钱七', 0);
|
||||
|
||||
INSERT INTO `app_department` (`name`, `parent_id`, `description`) VALUES
|
||||
('技术部', 0, '负责技术开发和维护'),
|
||||
('产品部', 0, '负责产品设计和规划'),
|
||||
('市场部', 0, '负责市场推广和销售'),
|
||||
('前端组', 1, '负责前端开发'),
|
||||
('后端组', 1, '负责后端开发');
|
||||
|
||||
INSERT INTO `app_product` (`title`, `description`, `price`, `stock`, `category_id`, `brand`, `sales_count`) VALUES
|
||||
('苹果手机', '最新款苹果手机,性能强劲', 6999.00, 100, 1, '苹果', 50),
|
||||
('华为手机', '国产精品手机,拍照出色', 4999.00, 200, 1, '华为', 80),
|
||||
('小米手机', '性价比之王,配置丰富', 2999.00, 300, 1, '小米', 120),
|
||||
('联想笔记本', '商务办公首选,稳定可靠', 5999.00, 50, 2, '联想', 30),
|
||||
('戴尔笔记本', '游戏性能出色,散热良好', 8999.00, 30, 2, '戴尔', 15);
|
||||
|
||||
INSERT INTO `app_order` (`order_no`, `user_id`, `product_id`, `quantity`, `price`, `amount`, `final_amount`, `status`, `created_time`) VALUES
|
||||
('ORD202301150001', 1, 1, 1, 6999.00, 6999.00, 6999.00, 'paid', '2023-01-15 15:30:00'),
|
||||
('ORD202301160001', 2, 2, 2, 4999.00, 9998.00, 9998.00, 'paid', '2023-01-16 10:20:00'),
|
||||
('ORD202301170001', 3, 3, 1, 2999.00, 2999.00, 2999.00, 'completed', '2023-01-17 14:15:00'),
|
||||
('ORD202301180001', 1, 4, 1, 5999.00, 5999.00, 5999.00, 'pending', '2023-01-18 16:45:00'),
|
||||
('ORD202301190001', 4, 5, 1, 8999.00, 8999.00, 8999.00, 'cancelled', '2023-01-19 11:30:00');
|
||||
|
||||
INSERT INTO `app_order_detail` (`order_id`, `product_id`, `product_title`, `price`, `quantity`, `amount`) VALUES
|
||||
(1, 1, '苹果手机', 6999.00, 1, 6999.00),
|
||||
(2, 2, '华为手机', 4999.00, 2, 9998.00),
|
||||
(3, 3, '小米手机', 2999.00, 1, 2999.00),
|
||||
(4, 4, '联想笔记本', 5999.00, 1, 5999.00),
|
||||
(5, 5, '戴尔笔记本', 8999.00, 1, 8999.00);
|
||||
|
||||
INSERT INTO `app_payment_log` (`user_id`, `order_id`, `type`, `amount`, `method`, `status`, `description`) VALUES
|
||||
(1, 1, 'order_payment', 6999.00, 'balance', 'success', '订单支付'),
|
||||
(2, 2, 'order_payment', 9998.00, 'alipay', 'success', '订单支付'),
|
||||
(3, 3, 'order_payment', 2999.00, 'wechat', 'success', '订单支付'),
|
||||
(2, NULL, 'recharge', 10000.00, 'alipay', 'success', '账户充值'),
|
||||
(3, NULL, 'recharge', 5000.00, 'wechat', 'success', '账户充值');
|
||||
|
||||
-- 创建索引优化查询性能
|
||||
CREATE INDEX idx_user_email_status ON app_user(email, status);
|
||||
CREATE INDEX idx_order_user_status ON app_order(user_id, status);
|
||||
CREATE INDEX idx_order_created_status ON app_order(created_time, status);
|
||||
CREATE INDEX idx_product_category_status ON app_product(category_id, status);
|
||||
|
||||
-- 创建视图(可选)
|
||||
CREATE OR REPLACE VIEW v_user_order_stats AS
|
||||
SELECT
|
||||
u.id as user_id,
|
||||
u.name as user_name,
|
||||
u.email,
|
||||
u.level,
|
||||
COUNT(o.id) as order_count,
|
||||
COALESCE(SUM(o.final_amount), 0) as total_amount,
|
||||
COALESCE(AVG(o.final_amount), 0) as avg_amount,
|
||||
MAX(o.created_time) as last_order_time
|
||||
FROM app_user u
|
||||
LEFT JOIN app_order o ON u.id = o.user_id AND o.status IN ('paid', 'completed')
|
||||
WHERE u.status = 1
|
||||
GROUP BY u.id;
|
||||
|
||||
-- 存储过程示例(可选)
|
||||
DELIMITER //
|
||||
CREATE PROCEDURE GetUserOrderSummary(IN p_user_id BIGINT)
|
||||
BEGIN
|
||||
SELECT
|
||||
u.name,
|
||||
u.email,
|
||||
u.level,
|
||||
u.balance,
|
||||
COUNT(o.id) as order_count,
|
||||
COALESCE(SUM(CASE WHEN o.status = 'paid' THEN o.final_amount END), 0) as paid_amount,
|
||||
COALESCE(SUM(CASE WHEN o.status = 'completed' THEN o.final_amount END), 0) as completed_amount
|
||||
FROM app_user u
|
||||
LEFT JOIN app_order o ON u.id = o.user_id
|
||||
WHERE u.id = p_user_id AND u.status = 1
|
||||
GROUP BY u.id;
|
||||
END //
|
||||
DELIMITER ;
|
||||
|
||||
-- 显示表结构信息
|
||||
SELECT
|
||||
TABLE_NAME as '表名',
|
||||
TABLE_COMMENT as '表注释',
|
||||
TABLE_ROWS as '预估行数',
|
||||
ROUND(DATA_LENGTH/1024/1024, 2) as '数据大小(MB)'
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME LIKE 'app_%'
|
||||
ORDER BY TABLE_NAME;
|
||||
Reference in New Issue
Block a user