跳到主要内容

使用 ORM 操作数据库

使用 ORM 系统操作数据库可以减少 80% 以上的 SQL 编写并让程序逻辑变得更加清晰可读。

对于如何使用 ORM 系统来操作数据库你必须先阅读学习上一章内容:操作数据库 并配置好 MySQL 模块。

安装 ORM

yarn add zenorm
yarn add --dev @zenorm/generate @zenorm/generate-mysql

配置 ORM

在项目根目录创建文件 .dbgen.js 用于配置数据库表模型代码生成

.dbgen.js
/** @type {import("@zenorm/generate").GenerateConfig} */
module.exports = {
host: "localhost", // 数据库地址
port: 3306, // 数据库端口
user: "root", // 数据库用户名
password: "", // 数据库密码
database: "test", // 数据库名称
bindQuery: true, // 开启单应用绑定 Query 对象(数据库连接池句柄)
};

修改 package.json 文件在 scripts 中添加一行 dbgen 指令, 用于执行生成指令

package.json
{
"scripts": {
"dbgen": "zenorm-generate .dbgen.js"
}
}

生成模型代码

在项目中执行命令

yarn dbgen

你将会看到一些输出信息,并在项目目录 src/model 目录中看到 ORM 系统生成的模型文件。

绑定查询句柄

在单应用中,数据库是单一共享的,所以我们只需要绑定 MySQL 的查询句柄即可方便的使用 ORM 提供的对象查询。

修改 src/index.ts

src/index.ts
// 导入 ORM 生成的 bindQuery 方法
import { bindQuery } from './model';

.setup(modMySQL({
bindQuery, // ORM 绑定
pools: { ... } // 请按照上一章内容配置好 MySQL pools
}))

开始使用

创建文件 src/controller/orm.ts

src/controller/orm.ts
import { Context, QueryHelper, mapping } from "zenweb";
import { AB } from "zenorm";
import { Message, User } from "../model";

/**
* 在这个控制器里演示最基本的增删改查
*/
export class ORMController {
/**
* 读取数据
*/
@mapping({ path: '/orm/get' })
async get() {
const result = await User.find().all();
return { result };
}

/**
* 插入数据
*/
@mapping({ path: '/orm/create' })
async create(qh: QueryHelper) {
const data = qh.get({
name: "!trim1",
birthday: "!date",
});
const result = await User.create(data);
return { result };
}

/**
* 自动事务
*/
@mapping({ path: '/orm/tx1' })
async autoTransaction(ctx: Context, qh: QueryHelper) {
const data = qh.get({
from_user_id: "!int",
to_user_id: "!int",
content: "!trim1",
});
// 开启数据库事务
await ctx.mysql.transaction(async tx => {
// 插入消息
await Message.query(tx).create(data);
// 更新未读消息数
await User.query(tx).findByPk(data.to_user_id).update({
unreads: AB.incr('unreads'),
});
});
return 'ok';
}

/**
* 手动事务
*/
@mapping({ path: '/orm/tx2' })
async manualTransaction(ctx: Context, qh: QueryHelper) {
const data = qh.get({
from_user_id: "!int",
to_user_id: "!int",
content: "!trim1",
});
// 使用自动连接池取得一个数据库连接线程
await ctx.mysql.auto(async conn => {
// 开启当前线程事务
await conn.beginTransaction();
try {
// 插入消息
await Message.query(conn).create(data);
// 更新未读消息数
await User.query(conn).findByPk(data.to_user_id).update({
unreads: AB.incr('unreads'),
});
// 提交事务
await conn.commit();
} catch {
// 发生异常 - 回滚事务
await conn.rollback();
}
});
return 'ok';
}
}

以上示例代码功能与上一章内容:操作数据库 一致,但是一句 SQL 都没有写,代码可读性与维护性更好。

ORM 系统的强大之处远不止于此。更多用法请参考 ZenORM 文档。