JavaScript 数据库集成:8 个实现无缝数据管理和性能的关键方法
发布: (2025年12月11日 GMT+8 19:48)
4 min read
原文: Dev.to
Source: Dev.to
使用连接池管理数据库连接
为每个请求创建新连接既慢又浪费资源。连接池维护一组随时可用的连接,能够被取出、使用,然后再释放回池中。
import mysql from 'mysql2/promise';
class DatabasePool {
constructor() {
this.pool = mysql.createPool({
host: 'localhost',
user: 'app_user',
password: 'secure_password',
database: 'my_app_db',
waitForConnections: true,
connectionLimit: 20,
queueLimit: 0
});
}
async query(sql, values) {
let connection;
try {
connection = await this.pool.getConnection();
const [results] = await connection.execute(sql, values);
return results;
} catch (err) {
console.error('Database query failed:', err.message);
// Add retry logic for specific errors if needed
throw err;
} finally {
if (connection) connection.release();
}
}
}
export default new DatabasePool();
使用 ORM 进行面向对象的数据访问
对象关系映射器(ORM)让你可以把数据库行当作 JavaScript 对象和类来操作,减少编写原始 SQL 字符串的需求。
// user.model.js
import { Model, DataTypes } from 'sequelize';
import sequelize from '../config/database.js';
import Post from './post.model.js';
class User extends Model {}
User.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: { isEmail: true }
},
fullName: {
type: DataTypes.STRING,
allowNull: false
},
isActive: {
type: DataTypes.BOOLEAN,
defaultValue: true
}
}, {
sequelize,
modelName: 'User',
tableName: 'users'
});
// Relationships
User.hasMany(Post, { foreignKey: 'authorId' });
Post.belongsTo(User, { foreignKey: 'authorId' });
export default User;
示例操作
// Create a new user
const newUser = await User.create({
email: 'hello@example.com',
fullName: 'Jane Developer'
});
console.log(newUser.id);
// Find a user with their posts
const user = await User.findOne({
where: { email: 'hello@example.com' },
include: Post
});
console.log(user.fullName);
user.Posts.forEach(post => console.log(post.title));
// Update a user
await user.update({ isActive: false });
查询构建器:灵活且安全的 SQL 构造
当 ORM 显得过于笨重时,查询构建器提供链式 API,生成参数化的 SQL,防止注入攻击。
import knex from 'knex';
const db = knex({
client: 'mysql2',
connection: {
host: 'localhost',
user: 'app_user',
password: 'secure_password',
database: 'my_app_db'
}
});
// Dynamic user search
async function searchUsers(filters = {}) {
let query = db('users')
.select('id', 'fullName', 'email', 'created_at');
if (filters.name) {
query = query.where('fullName', 'like', `%${filters.name}%`);
}
if (filters.active !== undefined) {
query = query.where('isActive', filters.active);
}
if (filters.minDate) {
query = query.where('created_at', '>=', filters.minDate);
}
return await query
.orderBy('created_at', 'desc')
.limit(50);
}
// Usage
const activeUsers = await searchUsers({ active: true, name: 'Jane' });
使用迁移管理模式更改
迁移提供版本化的脚本,以安全地演进数据库模式。
// migrations/20230915_add_bio_to_users.js
export async function up(knex) {
await knex.schema.table('users', (table) => {
table.text('bio').nullable().after('fullName'); // Add column
table.index(['isActive'], 'idx_users_active'); // Add index
});
}
export async function down(knex) {
await knex.schema.table('users', (table) => {
table.dropIndex('idx_users_active');
table.dropColumn('bio');
});
}
运行迁移会应用新列和索引;回滚则会撤销这些更改。
持久化前的数据验证
在数据到达数据库之前先在 JavaScript 中进行验证,可提供更清晰的错误信息,并提前强制业务规则。
import Joi from 'joi';
const userSchema = Joi.object({
email: Joi.string().email().required(),
fullName: Joi.string().min(2).max(100).required(),
age: Joi.number().integer().min(13).max(120).optional(),
website: Joi.string().uri().allow('').optional()
});
在创建或更新记录之前使用 userSchema.validate(data)(或 validateAsync)进行验证。