如何用Node.js与Sequelize实现SQL数据库数据插入与模型创建?
基于Sequelize创建模型并插入数据的方案
一、Sequelize模型优化方案
你的当前方案用JSON类型存储config和points是可行的,但如果后续需要对嵌套字段做查询、统计,更推荐拆分关联模型,以下两种方案供你选择:
方案1:保持JSON类型存储(快速实现)
你的现有模型可以直接用,但需要修正几个细节:
- 移除不必要的
hash排除字段(模型里没定义这个属性) - 给JSON字段加默认值,避免空值
const { DataTypes } = require('sequelize'); module.exports = model; function model(sequelize) { const attributes = { config: { type: DataTypes.JSON, allowNull: false, defaultValue: {} // 默认空对象 }, points: { type: DataTypes.JSON, allowNull: false, defaultValue: [] // 默认空数组 }, // 单独存储user_id,方便后续按用户查询数据 user_id: { type: DataTypes.INTEGER, allowNull: false } }; const options = { timestamps: true, // 自动添加createdAt、updatedAt字段,便于追踪数据 tableName: 'interactive_images' // 自定义语义化表名 }; return sequelize.define('InteractiveImage', attributes, options); }
方案2:拆分关联模型(适合复杂查询场景)
如果后续需要单独查询某个point、修改tooltip内容,拆分模型更合理,避免JSON字段的操作限制:
- 主模型:
InteractiveImage(对应原config) - 关联模型:
Point(对应原points数组项) - 关联模型:
Tooltip(对应每个point的tooltip)
主模型:InteractiveImage.js
const { DataTypes } = require('sequelize'); module.exports = model; function model(sequelize) { const attributes = { config_id: { type: DataTypes.STRING, allowNull: false, unique: true // 原config.id设为唯一键 }, user_id: { type: DataTypes.INTEGER, allowNull: false }, imageurl: { type: DataTypes.STRING, allowNull: false }, name: { type: DataTypes.STRING, allowNull: false }, server: { type: DataTypes.STRING }, size: { type: DataTypes.STRING }, imageWidth: { type: DataTypes.STRING }, imageHeight: { type: DataTypes.STRING }, hide_logo: { type: DataTypes.TINYINT, defaultValue: 0 }, point_color: { type: DataTypes.STRING }, pulse: { type: DataTypes.BOOLEAN, defaultValue: false } }; const options = { timestamps: true, tableName: 'interactive_images' }; const InteractiveImage = sequelize.define('InteractiveImage', attributes, options); // 建立关联:一个InteractiveImage对应多个Point InteractiveImage.associate = function(models) { InteractiveImage.hasMany(models.Point, { foreignKey: 'interactive_image_id', onDelete: 'CASCADE' // 删除主数据时自动删除关联的points }); }; return InteractiveImage; }
Point模型:Point.js
const { DataTypes } = require('sequelize'); module.exports = model; function model(sequelize) { const attributes = { pointId: { type: DataTypes.STRING, allowNull: false, unique: true }, x: { type: DataTypes.FLOAT, allowNull: false }, y: { type: DataTypes.FLOAT, allowNull: false } }; const options = { timestamps: true, tableName: 'points' }; const Point = sequelize.define('Point', attributes, options); // 建立关联:一个Point对应一个Tooltip,同时关联主模型 Point.associate = function(models) { Point.hasOne(models.Tooltip, { foreignKey: 'point_id', onDelete: 'CASCADE' }); Point.belongsTo(models.InteractiveImage, { foreignKey: 'interactive_image_id' }); }; return Point; }
Tooltip模型:Tooltip.js
const { DataTypes } = require('sequelize'); module.exports = model; function model(sequelize) { const attributes = { tooltipId: { type: DataTypes.STRING, allowNull: false, unique: true }, title: { type: DataTypes.STRING, allowNull: false }, price: { type: DataTypes.STRING }, link: { type: DataTypes.STRING }, tooltipThumbnailUrl: { type: DataTypes.STRING }, right: { type: DataTypes.STRING }, left: { type: DataTypes.STRING }, top: { type: DataTypes.STRING } }; const options = { timestamps: true, tableName: 'tooltips' }; const Tooltip = sequelize.define('Tooltip', attributes, options); Tooltip.associate = function(models) { Tooltip.belongsTo(models.Point, { foreignKey: 'point_id' }); }; return Tooltip; }
二、数据插入实现
场景1:使用JSON类型模型插入
假设你已初始化Sequelize实例并导入模型:
const { sequelize } = require('./path/to/sequelize-config'); const InteractiveImage = require('./models/InteractiveImage')(sequelize); // 插入数据的异步函数 async function saveInteractiveData(dataToSave) { try { const newData = await InteractiveImage.create({ user_id: dataToSave.config.user_id, config: dataToSave.config, points: dataToSave.points }); console.log('数据插入成功:', newData.toJSON()); return newData; } catch (error) { console.error('插入失败:', error); throw error; } } // 调用函数插入目标数据 saveInteractiveData(dataToSave);
场景2:使用关联模型插入
用事务保证数据一致性,避免部分插入成功的情况:
const { sequelize } = require('./path/to/sequelize-config'); const InteractiveImage = require('./models/InteractiveImage')(sequelize); const Point = require('./models/Point')(sequelize); const Tooltip = require('./models/Tooltip')(sequelize); async function saveInteractiveDataWithRelations(dataToSave) { const transaction = await sequelize.transaction(); try { // 1. 插入主模型数据 const image = await InteractiveImage.create({ config_id: dataToSave.config.id, user_id: dataToSave.config.user_id, imageurl: dataToSave.config.imageurl, name: dataToSave.config.name, server: dataToSave.config.server, size: dataToSave.config.size, imageWidth: dataToSave.config.imageWidth, imageHeight: dataToSave.config.imageHeight, hide_logo: dataToSave.config.hide_logo, point_color: dataToSave.config.point_color, pulse: dataToSave.config.pulse }, { transaction }); // 2. 遍历points插入关联数据 for (const pointData of dataToSave.points) { const point = await Point.create({ pointId: pointData.pointId, x: pointData.x, y: pointData.y, interactive_image_id: image.id }, { transaction }); // 3. 插入对应的tooltip await Tooltip.create({ tooltipId: pointData.tooltip.toltipId, title: pointData.tooltip.title, price: pointData.tooltip.price, link: pointData.tooltip.link, tooltipThumbnailUrl: pointData.tooltip.tooltipThumbnailUrl, right: pointData.tooltip.right, left: pointData.tooltip.left, top: pointData.tooltip.top, point_id: point.id }, { transaction }); } // 提交事务 await transaction.commit(); console.log('关联数据插入成功'); return image; } catch (error) { // 回滚事务 await transaction.rollback(); console.error('关联数据插入失败:', error); throw error; } } // 调用函数插入目标数据 saveInteractiveDataWithRelations(dataToSave);
内容的提问来源于stack exchange,提问作者The Dead Man
相关产品推荐
相关产品推荐

