epii-db-orm
v1.1.5
Published
## 1. 框架简介
Readme
epii-db-orm 框架详细说明文档
1. 框架简介
epii-orm 是一个轻量级的 Node.js 数据库 ORM 框架,专注于提供简洁易用的数据库操作接口。它采用链式调用风格,支持自动 SQL 构建,使数据库操作更加直观和高效。
1.1 主要特点
- 链式调用:支持流畅的链式方法调用,代码更加简洁易读
- SQL 自动构建:自动生成 SQL 语句,减少手动编写 SQL 的工作量
- 丰富的查询条件:提供多种查询条件构建方法,支持复杂查询
- 事务支持:内置事务处理机制,确保数据操作的原子性
- TypeScript 支持:使用 TypeScript 编写,提供完整的类型定义
- 轻量级设计:核心代码精简,无依赖,易于集成和使用
1.2 适用场景
- 小型到中型的 Node.js 项目
- 需要简洁数据库操作接口的项目
- 对 SQL 语句构建有需求的项目
- 使用 TypeScript 的项目
2. 安装与配置
2.1 安装
npm i epii-db-orm -S2.2 数据库连接配置
import { Db } from "epii-db-orm";
// 设置数据表的前缀
Db.config.tablePrefix = "";
// 设置数据库连接(单个连接)
Db.config.connection = mysqlConnection; // mysql2 或其他数据库连接对象
// 或设置连接池
// Db.config.connectionPool = mysqlPool; // 数据库连接池对象
// SQL 语句回调(可选)
Db.config.onSql = function (sql) {
console.log(sql); // 打印执行的 SQL 语句
};2.3 连接对象要求
连接对象需要实现以下接口:
interface IConnection {
query<T>(sql: string, params?: Array<string | number>): Promise<T>;
execute<T>(sql: string, params?: Array<string | number>): Promise<T>;
beginTransaction(): Promise<void>;
commit(): Promise<void>;
rollback(): Promise<void>;
}
interface IPool extends IConnection {
createConnection(): Promise<IConnection>;
}3. 核心概念与架构
3.1 核心模块
| 模块 | 职责 | 文件位置 | |------|------|----------| | Db | 数据库连接管理,提供操作入口 | src/Db.ts | | Query | 查询构建器,提供链式查询方法 | src/Query.ts | | SqlBuilder | SQL 语句构建器 | src/SqlBuilder.ts | | WhereData | 条件构建器 | src/map/WhereData.ts | | FieldData | 字段数据构建器 | src/map/FieldData.ts |
3.2 工作流程
- 通过
Db.name()创建 Query 实例 - 链式调用 Query 方法设置查询条件
- 调用执行方法(如 select、find、insert 等)
- SqlBuilder 生成 SQL 语句
- 通过数据库连接执行 SQL
- 返回执行结果
4. 基础操作
4.1 数据查询
查询单个数据
// 查询 id=1 的数据
const user = await Db.name("user").where("id", 1).find();
// 等价于: SELECT * FROM user WHERE id = 1 LIMIT 1
// 也可以直接传递 id
const user = await Db.name("user").find(1);查询多条数据
// 查询所有数据
const users = await Db.name("user").select();
// 等价于: SELECT * FROM user
// 查询指定字段
const userNames = await Db.name("user").field("name").select();
// 等价于: SELECT name FROM user
// 查询多个字段
const userInfo = await Db.name("user").field("id, name, age").select();
// 等价于: SELECT id, name, age FROM user条件查询
// 基本条件
const users = await Db.name("user").where("age", ">", 18).select();
// 复杂条件
const users = await Db.name("user")
.where("status", 1)
.whereLike("name", "张%")
.whereBetween("age", 18, 30)
.select();4.2 数据插入
插入单条数据
// 插入单条数据
const insertId = await Db.name("user").insert({
name: "张三",
age: 25,
email: "[email protected]"
});
// 等价于: INSERT INTO user (name, age, email) VALUES (?, ?, ?)插入多条数据
// 插入多条数据
const count = await Db.name("user").insertAll([
{ name: "张三", age: 25 },
{ name: "李四", age: 26 },
{ name: "王五", age: 27 }
]);
// 等价于: INSERT INTO user (name, age) VALUES (?, ?), (?, ?), (?, ?)4.3 数据更新
// 更新数据
const affectedRows = await Db.name("user")
.where("id", 1)
.update({ name: "张三(更新)", age: 26 });
// 等价于: UPDATE user SET name = ?, age = ? WHERE id = ?
// 使用 FieldData 进行复杂更新
import { FieldData } from "epii-db-orm";
const fieldData = new FieldData();
fieldData.put("name", "张三")
.putInc("age", 1); // age = age + 1
const affectedRows = await Db.name("user")
.where("id", 1)
.update(fieldData);4.4 数据删除
// 删除指定 ID 的数据
const affectedRows = await Db.name("user").delete(1);
// 等价于: DELETE FROM user WHERE id = 1
// 删除符合条件的数据
const affectedRows = await Db.name("user")
.where("age", "<", 18)
.delete();
// 等价于: DELETE FROM user WHERE age < ?注意:删除操作必须设置 where 条件,否则会抛出错误。
5. 高级查询
5.1 排序
// 升序排序
const users = await Db.name("user").order("age", "asc").select();
// 等价于: SELECT * FROM user ORDER BY age asc
// 降序排序
const users = await Db.name("user").order("create_time", "desc").select();
// 等价于: SELECT * FROM user ORDER BY create_time desc
// 多字段排序
const users = await Db.name("user")
.order("age", "asc")
.order("create_time", "desc")
.select();
// 等价于: SELECT * FROM user ORDER BY age asc, create_time desc5.2 分组与聚合
// 分组查询
const result = await Db.name("order")
.field("user_id, COUNT(*) as order_count, SUM(amount) as total_amount")
.group("user_id")
.select();
// 等价于: SELECT user_id, COUNT(*) as order_count, SUM(amount) as total_amount FROM order GROUP BY user_id
// 分组加筛选
const result = await Db.name("order")
.field("user_id, COUNT(*) as order_count")
.group("user_id")
.having("order_count > 5")
.select();
// 等价于: SELECT user_id, COUNT(*) as order_count FROM order GROUP BY user_id HAVING order_count > 55.3 表连接
// 左连接
const result = await Db.name("user")
.alias("u")
.field("u.id, u.name, r.role_name")
.leftJoin("role as r", "u.role_id = r.id")
.select();
// 等价于: SELECT u.id, u.name, r.role_name FROM user as u LEFT JOIN role as r ON u.role_id = r.id
// 右连接
const result = await Db.name("user")
.rightJoin("profile", "user.id = profile.user_id")
.select();
// 内连接
const result = await Db.name("user")
.innerJoin("order", "user.id = order.user_id")
.select();5.4 复杂条件
使用 WhereData
import { WhereData } from "epii-db-orm";
const where = new WhereData();
where.put("status", "1")
.putLike("name", "张%")
.putBetween("age", "18", "30")
.putIn("id", [1, 2, 3, 4, 5])
.putSymbol("score", ">", "80");
const users = await Db.name("user").where(where).select();
// 等价于: SELECT * FROM user WHERE status = 1 AND name like '张%' AND age between 18 and 30 AND id in (1,2,3,4,5) AND score > 80逻辑或条件
const users = await Db.name("user")
.where("status", "1")
.whereOr("age", "<", "18")
.whereOr("age", ">", "60")
.select();
// 等价于: SELECT * FROM user WHERE status = 1 OR age < 18 OR age > 606. 事务处理
6.1 基本事务
import { DbTransaction } from "epii-db-orm";
try {
const result = await DbTransaction(async (db) => {
// 在事务中执行操作
const userId = await db.name("user").insert({
name: "张三",
age: 25
});
await db.name("profile").insert({
user_id: userId,
address: "北京市"
});
return { success: true, userId };
});
console.log("事务执行成功:", result);
} catch (error) {
console.error("事务执行失败:", error);
// 事务会自动回滚
}6.2 手动事务
const connection = await Db.createConnection();
try {
await connection.beginTransaction();
// 执行操作
await connection.query("INSERT INTO user (name) VALUES (?)", ["张三"]);
await connection.query("UPDATE user SET age = ? WHERE name = ?", [25, "张三"]);
await connection.commit();
console.log("事务执行成功");
} catch (error) {
await connection.rollback();
console.error("事务执行失败:", error);
} finally {
// 释放连接(如果使用连接池)
// connection.release();
}7. 高级功能
7.1 数据映射
// 映射查询结果
const users = await Db.name("user")
.where("status", "1")
.map(user => ({
id: parseInt(user.id),
name: user.name,
age: parseInt(user.age),
isActive: user.status === "1",
createdAt: new Date(user.create_time)
}))
.select();
// 结果会自动应用映射函数7.2 字段操作
import { FieldData } from "epii-db-orm";
// 使用 FieldData 进行复杂更新
const fieldData = new FieldData();
fieldData.put("name", "张三")
.putInc("login_count", 1) // login_count = login_count + 1
.putDec("points", 5) // points = points - 5
.putExp("update_time", "NOW()"); // update_time = NOW()
await Db.name("user").where("id", 1).update(fieldData);7.3 原生 SQL
// 执行原生 SQL 查询
const users = await Db.query("SELECT * FROM user WHERE age > ?", [18]);
// 执行原生 SQL 语句
const result = await Db.execute("UPDATE user SET status = ? WHERE id = ?", [1, 1]);8. 性能优化
8.1 最佳实践
- 使用索引:确保查询条件中的字段有适当的索引
- 限制查询字段:只查询需要的字段,使用
field方法 - 限制结果集:使用
limit限制返回数据量 - 批量操作:使用
insertAll进行批量插入 - 使用连接池:高并发场景下使用连接池
- 避免全表扫描:始终设置 where 条件
- 合理使用缓存:对频繁查询的数据使用缓存
8.2 性能对比
| 操作 | 传统 SQL | epii-orm | |------|----------|----------| | 简单查询 | 直接编写 SQL | 链式调用,自动生成 SQL | | 复杂查询 | 复杂 SQL 语句 | 模块化条件构建 | | 批量操作 | 多条 SQL 语句 | 单次批量操作 | | 事务处理 | 手动管理 | 自动事务管理 |
9. 常见问题与解决方案
9.1 连接问题
问题:执行操作时提示 "connection is null"
解决方案:确保在操作前设置了数据库连接或连接池
9.2 事务问题
问题:事务执行失败
解决方案:
- 检查数据库引擎是否支持事务(如 MySQL 的 MyISAM 不支持)
- 确保所有操作都在事务回调中执行
- 检查是否有未捕获的异常
9.3 性能问题
问题:查询速度慢
解决方案:
- 添加适当的索引
- 限制查询字段和结果集
- 使用连接池
- 优化查询条件
9.4 类型问题
问题:TypeScript 类型错误
解决方案:
- 查看类型定义文件了解正确的类型
- 使用泛型指定返回类型
- 确保传递正确类型的参数
10. 完整示例
10.1 用户管理系统示例
import { Db, WhereData, DbTransaction } from "epii-db-orm";
// 配置数据库连接
Db.config.connectionPool = mysqlPool;
// 用户服务类
class UserService {
// 创建用户
async createUser(userData) {
return await DbTransaction(async (db) => {
const userId = await db.name("user").insert({
name: userData.name,
email: userData.email,
age: userData.age,
create_time: new Date().toISOString()
});
await db.name("user_profile").insert({
user_id: userId,
address: userData.address,
phone: userData.phone
});
return userId;
});
}
// 获取用户列表
async getUserList(params) {
const where = new WhereData();
if (params.status) {
where.put("status", params.status);
}
if (params.keyword) {
where.putLike("name", `%${params.keyword}%`);
where.putLike("email", `%${params.keyword}%`);
}
return await Db.name("user")
.where(where)
.order("create_time", "desc")
.limit(params.pageSize, (params.page - 1) * params.pageSize)
.select();
}
// 获取用户详情
async getUserDetail(userId) {
return await Db.name("user")
.alias("u")
.field("u.*, p.address, p.phone")
.leftJoin("user_profile as p", "u.id = p.user_id")
.where("u.id", userId)
.find();
}
// 更新用户信息
async updateUser(userId, updateData) {
return await Db.name("user").where("id", userId).update(updateData);
}
// 删除用户
async deleteUser(userId) {
return await DbTransaction(async (db) => {
await db.name("user_profile").where("user_id", userId).delete();
await db.name("user").where("id", userId).delete();
return true;
});
}
}
export default new UserService();11. API 参考
11.1 Db 类
| 方法 | 描述 | 参数 | 返回值 | |------|------|------|--------| | name(tableName) | 创建 Query 实例 | tableName: string 表名 | Query 实例 | | table(tableName) | 创建 Query 实例(不使用前缀) | tableName: string 表名 | Query 实例 | | query(sql, params) | 执行原生 SQL 查询 | sql: string SQL 语句params: Array 参��� | Promise 查询结果 | | execute(sql, params) | 执行原生 SQL 语句 | sql: string SQL 语句params: Array 参数 | Promise 执行结果 | | createConnection() | 创建数据库连接 | 无 | Promise 连接对象 |
11.2 Query 类
| 方法 | 描述 | 参数 | 返回值 | |------|------|------|--------| | where(field, value) | 添加 WHERE 条件 | field: string 字段名value: any 值 | Query 实例 | | where(field, op, value) | 添加带操作符的条件 | field: string 字段名op: string 操作符value: any 值 | Query 实例 | | where(condition) | 添加条件字符串 | condition: string 条件字符串 | Query 实例 | | where(whereData) | 添加 WhereData 条件 | whereData: WhereData 条件对象 | Query 实例 | | whereId(id) | 添加 ID 条件 | id: number ID 值 | Query 实例 | | whereOp(field, op, value) | 添加操作符条件 | field: string 字段名op: string 操作符value: any 值 | Query 实例 | | whereLike(field, value) | 添加 LIKE 条件 | field: string 字段名value: string 匹配值 | Query 实例 | | whereBetween(field, start, end) | 添加 BETWEEN 条件 | field: string 字段名start: any 开始值end: any 结束值 | Query 实例 | | whereIn(field, values) | 添加 IN 条件 | field: string 字段名values: Array 值数组 | Query 实例 | | whereOr(field, value) | 添加 OR 条件 | field: string 字段名value: any 值 | Query 实例 | | field(fields) | 指定查询字段 | fields: string 字段列表 | Query 实例 | | order(field, direction) | 添加排序 | field: string 字段名direction: string 方向 (asc/desc) | Query 实例 | | limit(limit, offset) | 限制结果集 | limit: number 数量offset: number 偏移量 | Query 实例 | | group(field) | 添加分组 | field: string 分组字段 | Query 实例 | | having(condition) | 添加分组条件 | condition: string 条件 | Query 实例 | | alias(alias) | 设置表别名 | alias: string 别名 | Query 实例 | | join(table, condition, type) | 添加表连接 | table: string 表名condition: string 连接条件type: string 连接类型 | Query 实例 | | leftJoin(table, condition) | 添加左连接 | table: string 表名condition: string 连接条件 | Query 实例 | | rightJoin(table, condition) | 添加右连接 | table: string 表名condition: string 连接条件 | Query 实例 | | innerJoin(table, condition) | 添加内连接 | table: string 表名condition: string 连接条件 | Query 实例 | | map(func) | 设置结果映射函数 | func: Function 映射函数 | Query 实例 | | data(data) | 设置数据 | data: Object/FieldData 数据 | Query 实例 | | select() | 查询多条数据 | 无 | Promise<Array> 结果数组 | | find(id) | 查询单条数据 | id: number (可选) ID 值 | Promise<T|null> 结果对象或 null | | value(field, defaultValue) | 获取单个字段值 | field: string 字段名defaultValue: any 默认值 | Promise 字段值 | | count() | 统计记录数 | 无 | Promise 记录数 | | column(field) | 获取单列数据 | field: string 字段名 | Promise<Array> 字段值数组 | | insert(data) | 插入数据 | data: Object/FieldData 数据 | Promise 插入 ID | | insertAll(dataList) | 批量插入数据 | dataList: Array<Object/FieldData> 数据列表 | Promise 影响行数 | | update(data) | 更新数据 | data: Object/FieldData 数据 | Promise 影响行数 | | delete(id) | 删除数据 | id: number (可选) ID 值 | Promise 影响行数 |
11.3 WhereData 类
| 方法 | 描述 | 参数 | 返回值 | |------|------|------|--------| | put(field, value) | 添加等于条件 | field: string 字段名value: any 值 | WhereData 实例 | | putExp(field, exp) | 添加表达式条件 | field: string 字段名exp: string 表达式 | WhereData 实例 | | putLike(field, value) | 添加 LIKE 条件 | field: string 字段名value: string 匹配值 | WhereData 实例 | | putIn(field, values) | 添加 IN 条件 | field: string 字段名values: Array 值数组 | WhereData 实例 | | putNotIn(field, values) | 添加 NOT IN 条件 | field: string 字段名values: Array 值数组 | WhereData 实例 | | putSymbol(field, op, value) | 添加带操作符的条件 | field: string 字段名op: string 操作符value: string 值 | WhereData 实例 | | putBetween(field, start, end) | 添加 BETWEEN 条件 | field: string 字段名start: string 开始值end: string 结束值 | WhereData 实例 | | putNotBetween(field, start, end) | 添加 NOT BETWEEN 条件 | field: string 字段名start: string 开始值end: string 结束值 | WhereData 实例 | | static make(key, value) | 创建 WhereData 实例 | key: string 字段名value: string 值 | WhereData 实例 |
11.4 FieldData 类
| 方法 | 描述 | 参数 | 返回值 | |------|------|------|--------| | put(field, value) | 添加字段值 | field: string 字段名value: any 值 | FieldData 实例 | | put(fieldData) | 添加多个字段值 | fieldData: Object/Map 字段数据 | FieldData 实例 | | putInc(field, step) | 添加自增操作 | field: string 字段名step: number 步长 | FieldData 实例 | | putDec(field, step) | 添加自减操作 | field: string 字段名step: number 步长 | FieldData 实例 | | putExp(field, exp) | 添加表达式操作 | field: string 字段名exp: string 表达式 | FieldData 实例 | | static make(key, value) | 创建 FieldData 实例 | key: string/Object/Map 字段名或数据value: any 值 | FieldData 实例 |
12. 版本历史
| 版本 | 日期 | 主要变更 | |------|------|----------| | 1.1.4 | 2024-01 | 优化 SQL 构建逻辑 | | 1.1.3 | 2024-01 | 修复事务处理问题 | | 1.1.2 | 2024-01 | 添加数据映射功能 | | 1.1.1 | 2024-01 | 完善 TypeScript 类型定义 | | 1.1.0 | 2024-01 | 增加事务支持 | | 1.0.0 | 2024-01 | 初始版本 |
13. 贡献与开发
13.1 开发环境搭建
# 克隆代码
git clone <repository-url>
# 安装依赖
npm install
# 编译 TypeScript
npm run build
# 运行测试
npm test13.2 目录结构
epii-orm/
├── src/ # 源代码
│ ├── libs/ # 工具库
│ ├── map/ # 映射类
│ ├── Db.ts # 数据库连接管理
│ ├── Query.ts # 查询构建器
│ ├── SqlBuilder.ts # SQL 构建器
│ └── index.ts # 导出入口
├── dist/ # 编译产物
├── package.json # 包配置
├── tsconfig.json # TypeScript 配置
└── readme.md # 说明文档13.3 提交规范
- 代码风格:遵循 TypeScript 标准风格
- 提交信息:使用清晰的提交信息
- 测试:确保所有测试通过
- 文档:更新相关文档
14. 许可证
本项目采用 ISC 许可证。详见 LICENSE 文件。
15. 联系与支持
- 问题反馈:在 GitHub 仓库提交 Issue
- 功能请求:在 GitHub 仓库提交 Issue
- 代码贡献:Fork 仓库并提交 Pull Request
结语:epii-orm 是一个轻量级但功能强大的数据库 ORM 框架,它提供了简洁易用的 API,使数据库操作更加直观和高效。通过本文档的学习,您应该已经掌握了 epii-orm 的核心功能和使用方法。如果您有任何问题或建议,欢迎随时反馈。
