在企业级应用开发中,数据库的选择往往需要根据项目规模、性能需求、部署环境等因素灵活调整。RuoYi-Eggjs 项目通过精心设计的数据库抽象层,实现了 一行配置切换数据库 的能力,同时引入了 Java 开发者熟悉的 MyBatis XML 风格来编写 SQL,让业务逻辑与数据访问完美分离。
项目原生支持三种主流数据库:
| 数据库 | 插件 | 适用场景 |
|---|---|---|
| MySQL | ruoyi-eggjs-mysql | 生产环境首选,功能完善 |
| PostgreSQL | ruoyi-eggjs-pgsql | 复杂查询、地理数据 |
| SQLite | ruoyi-eggjs-sqlite | 开发测试、轻量部署 |
在 config/config.default.js 中,只需修改 driver 字段即可切换数据库:
// 数据库映射配置
config.database = {
master: {
driver: "mysql", // 切换为 "pgsql" 或 "sqlite" 即可
instance: "ruoyi", // 数据库实例名称
},
slave: {
driver: "mysql", // 从库配置(读操作)
instance: "ruoyi",
},
readWriteSplit: false, // 是否启用读写分离
};切换数据库只需三步:
driver 为目标数据库类型config.local.js 中配置对应的数据库连接对于高并发场景,可以启用读写分离:
config.database = {
master: {
driver: "mysql",
instance: "ruoyi_master", // 主库(写操作)
},
slave: {
driver: "mysql",
instance: "ruoyi_slave", // 从库(读操作)
},
readWriteSplit: true, // 启用读写分离
};// config/config.local.js
config.mysql = {
camelCase: true, // 自动驼峰转换:user_name -> userName
clients: {
ruoyi: {
host: "127.0.0.1",
user: "root",
password: "your_password",
database: "ruoyi",
},
},
};config.pgsql = {
camelCase: true,
clients: {
ruoyi: {
host: "127.0.0.1",
user: "ruoyi",
password: "your_password",
database: "ruoyi",
},
},
};config.sqlite = {
camelCase: true,
clients: {
ruoyi: {
database: "./ruoyi.db", // 数据库文件路径
},
},
};项目采用分数据库类型的目录结构,便于管理不同数据库的 SQL 差异:
mapper/
├── mysql/ # MySQL 专用 SQL
│ └── ruoyi/
│ ├── SysUserMapper.xml
│ ├── SysRoleMapper.xml
│ └── ...
├── pgsql/ # PostgreSQL 专用 SQL
│ └── ruoyi/
│ └── ...
└── sqlite/ # SQLite 专用 SQL
└── ruoyi/
└── ...<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper/mysql/ruoyi/SysUserMapper.xml">
<!-- SQL 片段复用 -->
<sql id="selectUserVo">
select u.user_id, u.user_name, u.nick_name, u.email,
u.phonenumber, u.status, u.create_time
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
</sql>
<!-- 动态条件查询 -->
<selects id="selectUserList" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.del_flag = '0'
<if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%')
</if>
<if test="status != null and status != ''">
AND u.status = #{status}
</if>
<if test="params.beginTime != null and params.beginTime != ''">
AND u.create_time >= #{params.beginTime}
</if>
</selects>
<!-- 动态更新 -->
<update id="updateUser">
update sys_user
<set>
<if test="nickName != null and nickName != ''">
nick_name = #{nickName},
</if>
<if test="email != null">email = #{email},</if>
<if test="status != null and status != ''">
status = #{status},
</if>
update_time = sysdate()
</set>
where user_id = #{userId}
</update>
<!-- 批量删除 -->
<delete id="deleteUserByIds">
update sys_user set del_flag = '2' where user_id in
<foreach collection="array" item="userId"
open="(" separator="," close=")">
#{userId}
</foreach>
</delete>
</mapper>| 标签 | 说明 | 示例 |
|---|---|---|
<if> | 条件判断 | <if test="userName">...</if> |
<where> | 智能 WHERE 子句 | 自动处理首个 AND/OR |
<set> | 智能 SET 子句 | 自动处理末尾逗号 |
<foreach> | 循环遍历 | IN 查询、批量操作 |
<choose> | 多条件选择 | 类似 switch-case |
<sql> | SQL 片段定义 | 提取公共 SQL |
<include> | 引用 SQL 片段 | 复用公共 SQL |
项目配套的 CLI 工具可以根据 XML Mapper 自动生成 Service 层代码:
# 启动代码生成器(自动监听模式)
npm run mapper
# 或手动执行
psy mapper生成效果:
mapper/mysql/ruoyi/SysUserMapper.xml
↓ 自动生成
app/service/db/mysql/ruoyi/SysUserMapper.jsconst Service = require('egg').Service;
class SysUserMapperService extends Service {
mapper(sqlid, values, params) {
return this.app.mapper(
'mapper/mysql/ruoyi/SysUserMapper.xml',
sqlid, values, params
);
}
db() {
return this.app.mysql.get('ruoyi');
}
// 查询用户列表
async selectUserList(values, params) {
return await this.db().selects(
this.mapper('selectUserList', values, params)
);
}
// 更新用户
async updateUser(values, params) {
return await this.db().update(
this.mapper('updateUser', values, params)
);
}
// 批量删除
async deleteUserByIds(values, params) {
return await this.db().del(
this.mapper('deleteUserByIds', values, params)
);
}
}
module.exports = SysUserMapperService;// app/controller/system/user.js
class UserController extends Controller {
async list() {
const { ctx } = this;
const params = ctx.request.body;
// 调用自动生成的 Service
const users = await ctx.service.db.mysql.ruoyi
.sysUserMapper.selectUserList(
ctx.helper.page(params), // 自动分页
params
);
ctx.body = { code: 200, data: users };
}
async update() {
const { ctx } = this;
const user = ctx.request.body;
await ctx.service.db.mysql.ruoyi
.sysUserMapper.updateUser([user.userId], user);
ctx.body = { code: 200, msg: '更新成功' };
}
}内置分页辅助方法,自动计算 LIMIT 参数:
// 请求参数
{
"currentPage": 2,
"pageSize": 20,
"userName": "张三"
}
// 使用 ctx.helper.page() 自动注入分页参数
const sql = app.mapper(
'namespace',
'selectUserList',
ctx.helper.page(params), // 自动计算 [offset, limit]
params
);自动转义,防止 SQL 注入:
<select id="selectUser">
SELECT * FROM sys_user WHERE user_name = #{userName}
</select>用于表名、字段名等不可参数化的部分(注意安全性):
<select id="selectByColumn">
SELECT * FROM sys_user ORDER BY ${orderColumn} ${orderType}
</select># 1. 启动开发环境(自动生成 Mapper + 调试)
npm run dev
# 2. 编写/修改 XML Mapper 文件
# 3. CLI 自动检测变化并重新生成 Service
# 4. 在 Controller 中调用 Service{
"scripts": {
"dev": "npm-run-all -p mapper debug",
"mapper": "psy mapper",
"debug": "egg-bin debug",
"start": "egg-scripts start",
"stop": "egg-scripts stop"
}
}步骤 1:修改数据库映射配置
// config/config.default.js
config.database = {
master: {
driver: "sqlite", // 改为 sqlite
instance: "ruoyi",
},
slave: {
driver: "sqlite",
instance: "ruoyi",
},
readWriteSplit: false,
};步骤 2:配置 SQLite 连接
// config/config.local.js
config.sqlite = {
camelCase: true,
clients: {
ruoyi: {
database: "./ruoyi.db",
},
},
};步骤 3:导入数据
sqlite3 ruoyi.db < sql/sqlite/ry_20250522.sql步骤 4:重启应用
npm run devRuoYi-Eggjs 通过以下设计实现了灵活的多数据库支持:
这种设计让开发者可以:
真正实现了 一套代码,多库运行 的目标。
[1] ruoyi-eggjs: https://github.com/undsky/ruoyi-eggjs
[2] ruoyi-eggjs-mybatis: https://github.com/undsky/ruoyi-eggjs-mybatis
[3] ruoyi-eggjs-mysql: https://github.com/undsky/ruoyi-eggjs-mysql
[4] ruoyi-eggjs-pgsql: https://github.com/undsky/ruoyi-eggjs-pgsql
[5] ruoyi-eggjs-sqlite: https://github.com/undsky/ruoyi-eggjs-sqlite
[6] ruoyi-eggjs-cli: https://github.com/undsky/ruoyi-eggjs-cli