在 Sequelize 中,开发人员可以使用 get
和 set
方法自定义模型实例的属性的获取和设置行为。这给使用者提供了极大的自由度,非常类似于js中对象属性的getter和setter,用起来上手没有难度。本文列举几个在实际场景中使用get/set的典型例子。
示例1: 自定义格式化日期字段
设置模型的代码
const User = sequelize.define('User', {
username: Sequelize.STRING,
birthdate: {
type: Sequelize.DATE,
get() {
// 格式化日期为YYYY-MM-DD
return this.getDataValue('birthdate').toISOString().split('T')[0];
},
},
});
使用模型的代码
// 示例代码
// ...
// 获取所有用户的格式化出生日期
const users = await User.findAll();
// 格式化结果,包括虚拟字段
const formattedUsers = users.map(user => ({
id: user.id,
username: user.username,
formattedBirthdate: user.birthdate, // 访问虚拟字段
}));
// 发送响应
res.json({ users: formattedUsers });
示例2: 使用虚拟字段存储加密密码
设置模型的代码
const User = sequelize.define('User', {
username: Sequelize.STRING,
password: Sequelize.STRING,
salt: Sequelize.STRING, // 存储加密用的密钥
}, {
// 定义虚拟字段
virtualFields: ['hashedPassword'],
// 定义虚拟字段的getter和setter方法
getterMethods: {
hashedPassword() {
// 返回加密后的密码
return this.password + this.salt;
},
},
setterMethods: {
hashedPassword(value) {
// 在设置hashedPassword时分离密码和密钥
const parts = value.split(this.salt);
this.setDataValue('password', parts[0]);
this.setDataValue('salt', parts[1]);
},
},
});
// 使用虚拟字段
const user = await User.findByPk(1);
console.log(user.hashedPassword); // 访问虚拟字段
在这个例子中,通过定义虚拟字段hashedPassword
和相应的getter和setter方法,可以在模型中存储加密后的密码,并在查询和设置时进行处理。
使用模型的代码
// 示例代码
// ...
// 创建新用户并设置加密密码
const newUser = await User.create({
username: 'john_doe',
hashedPassword: 'encryptedPassword' + 'saltValue', // 设置虚拟字段
});
// 验证密码时访问虚拟字段
if (newUser.hashedPassword === 'encryptedPassword' + 'saltValue') {
// 密码验证成功
}
示例3: 计算用户年龄
设置模型的代码
const User = sequelize.define('User', {
name: Sequelize.STRING,
birthdate: Sequelize.DATE,
age: {
type: Sequelize.VIRTUAL,
get() {
// 计算用户年龄
const birthYear = new Date(this.birthdate).getFullYear();
const currentYear = new Date().getFullYear();
return currentYear - birthYear;
},
},
});
在这个例子中,使用 VIRTUAL
类型的字段 age
,并通过 get
方法计算用户的年龄。
使用模型的代码
// 示例代码
// ...
// 获取所有用户及其年龄
const users = await User.findAll();
// 格式化结果,包括虚拟字段
const formattedUsers = users.map(user => ({
id: user.id,
name: user.name,
age: user.age, // 访问虚拟字段
}));
// 发送响应
res.json({ users: formattedUsers });
示例4: 处理文章摘要
设置模型的代码
const Article = sequelize.define('Article', {
title: Sequelize.STRING,
content: Sequelize.TEXT,
summary: {
type: Sequelize.VIRTUAL,
get() {
// 提取文章内容的前100个字符作为摘要
return this.content ? this.content.substring(0, 100) : '';
},
},
});
在这个例子中,使用 VIRTUAL
类型的字段 summary
,通过 get
方法提取文章内容的前100个字符作为摘要。
注意这里使用的this.content
。
使用模型的代码
// 示例代码
// ...
// 获取所有文章及其摘要
const articles = await Article.findAll();
// 格式化结果,包括虚拟字段
const formattedArticles = articles.map(article => ({
id: article.id,
title: article.title,
summary: article.summary, // 访问虚拟字段
}));
// 发送响应
res.json({ articles: formattedArticles });
示例5: 计算订单总价
设置模型的代码
const Order = sequelize.define('Order', {
quantity: Sequelize.INTEGER,
pricePerUnit: Sequelize.FLOAT,
totalAmount: {
type: Sequelize.VIRTUAL,
get() {
// 计算订单总价
return this.quantity * this.pricePerUnit;
},
},
});
在这个例子中,使用 VIRTUAL
类型的字段 totalAmount
,通过 get
方法计算订单的总价。
使用模型的代码
// 示例代码
// ...
// 获取所有订单及其总价
const orders = await Order.findAll();
// 格式化结果,包括虚拟字段
const formattedOrders = orders.map(order => ({
id: order.id,
quantity: order.quantity,
pricePerUnit: order.pricePerUnit,
totalAmount: order.totalAmount, // 访问虚拟字段
}));
// 发送响应
res.json({ orders: formattedOrders });