ORM使用 #
一、ORM概述 #
1.1 什么是ORM? #
ORM(Object-Relational Mapping)是一种将对象模型映射到关系型数据库的技术。它允许开发者使用面向对象的方式操作数据库。
1.2 常用ORM #
| ORM | 数据库支持 | 特点 |
|---|---|---|
| Sequelize | MySQL, PostgreSQL, SQLite | 成熟稳定 |
| Prisma | MySQL, PostgreSQL, MongoDB | 类型安全 |
| TypeORM | MySQL, PostgreSQL, SQLite | TypeScript原生 |
| Mongoose | MongoDB | MongoDB专用 |
二、Sequelize #
2.1 安装 #
bash
npm install sequelize mysql2
2.2 连接数据库 #
javascript
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('myapp', 'root', 'password', {
host: 'localhost',
dialect: 'mysql',
logging: false
});
const testConnection = async () => {
try {
await sequelize.authenticate();
console.log('数据库连接成功');
} catch (error) {
console.error('数据库连接失败:', error);
}
};
module.exports = sequelize;
2.3 定义模型 #
javascript
const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING(50),
allowNull: false,
validate: {
notEmpty: true,
len: [2, 50]
}
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
validate: {
isEmail: true
}
},
password: {
type: DataTypes.STRING(255),
allowNull: false
},
role: {
type: DataTypes.ENUM('user', 'admin'),
defaultValue: 'user'
},
isActive: {
type: DataTypes.BOOLEAN,
defaultValue: true
}
}, {
tableName: 'users',
timestamps: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
hooks: {
beforeCreate: async (user) => {
if (user.password) {
user.password = await bcrypt.hash(user.password, 10);
}
}
}
});
module.exports = User;
2.4 关联关系 #
javascript
const User = require('./User');
const Post = require('./Post');
User.hasMany(Post, { foreignKey: 'authorId', as: 'posts' });
Post.belongsTo(User, { foreignKey: 'authorId', as: 'author' });
2.5 CRUD操作 #
javascript
const users = await User.findAll();
const user = await User.findByPk(id);
const user = await User.findOne({ where: { email } });
const user = await User.create({ name, email, password });
await User.update({ name: '新名字' }, { where: { id } });
await User.destroy({ where: { id } });
2.6 查询进阶 #
javascript
const users = await User.findAll({
where: {
role: 'admin',
isActive: true
},
attributes: ['id', 'name', 'email'],
include: [{
model: Post,
as: 'posts',
attributes: ['id', 'title']
}],
order: [['created_at', 'DESC']],
limit: 10,
offset: 0
});
const { count, rows } = await User.findAndCountAll({
limit: 10,
offset: 0
});
2.7 事务 #
javascript
const result = await sequelize.transaction(async (t) => {
const user = await User.create({ name, email, password }, { transaction: t });
await Profile.create({ userId: user.id, bio }, { transaction: t });
return user;
});
三、Prisma #
3.1 安装 #
bash
npm install prisma --save-dev
npx prisma init
3.2 Schema定义 #
prisma/schema.prisma:
prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @id @default(autoincrement())
name String @db.VarChar(50)
email String @unique @db.VarChar(100)
password String @db.VarChar(255)
role Role @default(USER)
isActive Boolean @default(true) @map("is_active")
posts Post[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("users")
}
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(200)
content String? @db.Text
authorId Int @map("author_id")
author User @relation(fields: [authorId], references: [id])
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("posts")
}
enum Role {
USER
ADMIN
}
3.3 客户端使用 #
javascript
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
const users = await prisma.user.findMany();
const user = await prisma.user.findUnique({ where: { id } });
const user = await prisma.user.findUnique({ where: { email } });
const user = await prisma.user.create({
data: { name, email, password }
});
const user = await prisma.user.update({
where: { id },
data: { name: '新名字' }
});
await prisma.user.delete({ where: { id } });
3.4 关联查询 #
javascript
const users = await prisma.user.findMany({
include: {
posts: true
}
});
const posts = await prisma.post.findMany({
include: {
author: {
select: {
id: true,
name: true,
email: true
}
}
}
});
3.5 分页查询 #
javascript
const page = 1;
const limit = 10;
const skip = (page - 1) * limit;
const [users, total] = await Promise.all([
prisma.user.findMany({
skip,
take: limit,
orderBy: { createdAt: 'desc' }
}),
prisma.user.count()
]);
3.6 事务 #
javascript
const result = await prisma.$transaction([
prisma.user.create({ data: { name, email, password } }),
prisma.profile.create({ data: { userId, bio } })
]);
const user = await prisma.$transaction(async (tx) => {
const user = await tx.user.create({ data: { name, email, password } });
await tx.profile.create({ data: { userId: user.id, bio } });
return user;
});
四、完整示例 #
4.1 Sequelize完整示例 #
models/index.js:
javascript
const Sequelize = require('sequelize');
const config = require('../config/database');
const sequelize = new Sequelize(config.database, config.username, config.password, {
host: config.host,
dialect: config.dialect,
logging: false
});
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
db.User = require('./User')(sequelize, Sequelize);
db.Post = require('./Post')(sequelize, Sequelize);
db.Comment = require('./Comment')(sequelize, Sequelize);
db.User.hasMany(db.Post, { foreignKey: 'authorId', as: 'posts' });
db.Post.belongsTo(db.User, { foreignKey: 'authorId', as: 'author' });
db.Post.hasMany(db.Comment, { foreignKey: 'postId', as: 'comments' });
db.Comment.belongsTo(db.Post, { foreignKey: 'postId' });
db.Comment.belongsTo(db.User, { foreignKey: 'authorId' });
module.exports = db;
services/userService.js:
javascript
const { User, Post } = require('../models');
const userService = {
async findAll(options = {}) {
const page = parseInt(options.page) || 1;
const limit = parseInt(options.limit) || 10;
const offset = (page - 1) * limit;
const { count, rows } = await User.findAndCountAll({
attributes: { exclude: ['password'] },
include: [{
model: Post,
as: 'posts',
attributes: ['id', 'title'],
required: false
}],
order: [['createdAt', 'DESC']],
limit,
offset
});
return {
users: rows,
pagination: {
page,
limit,
total: count,
totalPages: Math.ceil(count / limit)
}
};
},
async findById(id) {
return await User.findByPk(id, {
attributes: { exclude: ['password'] },
include: [{
model: Post,
as: 'posts'
}]
});
},
async create(userData) {
return await User.create(userData);
},
async update(id, userData) {
const [updated] = await User.update(userData, {
where: { id }
});
return updated > 0;
},
async delete(id) {
return await User.destroy({ where: { id } });
}
};
module.exports = userService;
五、ORM对比 #
| 特性 | Sequelize | Prisma |
|---|---|---|
| 学习曲线 | 中等 | 较低 |
| 类型安全 | 一般 | 优秀 |
| 查询语法 | 链式调用 | 对象语法 |
| 迁移工具 | 内置 | 内置 |
| 文档 | 完善 | 优秀 |
| 性能 | 良好 | 优秀 |
六、总结 #
ORM使用要点:
| 概念 | 说明 |
|---|---|
| 模型定义 | 定义数据结构和验证 |
| 关联关系 | 一对一、一对多、多对多 |
| CRUD | 增删改查操作 |
| 查询 | 条件、排序、分页 |
| 事务 | 保证数据一致性 |
下一步,让我们学习高级特性!
最后更新:2026-03-28