AgentStack
SKILL verified Apache-2.0 Self-run

Sequelize Xugudb Adapter

skill-kourou25-xugudb-dev-skills-sequelize-xugudb-adapter · by kourou25

Sequelize Node.js ORM 适配虚谷数据库(XuguDB)的完整指南。当用户需要将基于 Sequelize 的 Node.js 项目配置或适配到虚谷数据库时使用此技能,包括驱动安装、方言包配置、连接字符串、模型定义、CRUD 操作、事务处理等。适用于从 MySQL/PostgreSQL 迁移或新建虚谷数据库项目。

No reviews yet
0 installs
17 views
0.0% view→install

Install

$ agentstack add skill-kourou25-xugudb-dev-skills-sequelize-xugudb-adapter

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Sequelize Xugudb Adapter? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Sequelize 虚谷数据库适配指南

概述

本技能提供 Sequelize 适配虚谷数据库(XuguDB)的完整流程。Sequelize 是一个基于 promise 的 Node.js ORM 框架,通过虚谷数据库专用的方言包 xugu-dialect,可以无缝集成 Sequelize 框架的各种功能,包括模型定义、CRUD 操作、事务处理、关联关系等。

适配流程

在开始适配前,按以下顺序检查和修改:

1. 依赖安装 → 2. 连接配置 → 3. 模型定义 → 4. 数据库迁移 → 5. CRUD 操作 → 6. 事务处理 → 7. 性能优化 → 8. 测试验证

第一步:安装依赖

安装 Sequelize

# 安装 Sequelize 和相关依赖
npm install sequelize dotenv

# 或使用 yarn
yarn add sequelize dotenv

安装虚谷数据库驱动

  1. 获取方言包 - 从虚谷数据库官方下载 Sequelize 方言压缩包(xugu-dialect
  2. 解压方言包 - 解压压缩包获取方言文件
  3. 放置方言文件 - 将解压后的 xugu-dialect 目录移动到 Sequelize 的 dialects 目录中,通常路径为 node_modules/sequelize/lib/dialects/
  4. 替换 MySQL 方言 - 将 xugu-dialect 目录重命名为 mysql
  5. 备份原 MySQL 方言 - 为避免覆盖原有文件,建议将原 mysql 目录重命名为 mysql-bak 进行备份
  6. 放置 Node.js 驱动 - 将 XuguDB 的 Node.js 驱动文件夹放置到 node_modules/sequelize/lib/dialects/abstract/ 目录下

验证驱动安装

// 测试 Sequelize 连接
const { Sequelize } = require('sequelize');

const sequelize = new Sequelize('SYSTEM', 'SYSDBA', 'SYSDBA', {
  host: '127.0.0.1',
  dialect: 'mysql',  // 使用 mysql dialect(已替换为 xugu-dialect)
  logging: false
});

async function testConnection() {
  try {
    await sequelize.authenticate();
    console.log('Connection has been established successfully.');
  } catch (error) {
    console.error('Unable to connect to the database:', error);
  }
}

testConnection();

第二步:配置连接

环境变量配置

创建 .env 文件配置数据库连接参数:

# 数据库配置
DB_NAME=SYSTEM
DB_USER=SYSDBA
DB_PASSWORD=SYSDBA
DB_HOST=127.0.0.1
DB_PORT=5138

# 应用配置
NODE_ENV=development
PORT=3000

数据库配置文件

创建 config/database.js 配置文件:

const { Sequelize } = require('sequelize');
require('dotenv').config();

const sequelize = new Sequelize(
  process.env.DB_NAME,
  process.env.DB_USER,
  process.env.DB_PASSWORD,
  {
    host: process.env.DB_HOST,
    port: process.env.DB_PORT || 5138,
    dialect: 'mysql',  // 使用 mysql dialect(已替换为 xugu-dialect)
    logging: process.env.NODE_ENV === 'development' ? console.log : false,
    pool: {
      max: 20,          // 最大连接数
      min: 5,           // 最小连接数
      acquire: 30000,   // 获取连接超时时间(毫秒)
      idle: 10000       // 连接空闲超时时间(毫秒)
    },
    define: {
      timestamps: true,  // 自动添加 createdAt 和 updatedAt 字段
      underscored: true, // 使用下划线命名法
      freezeTableName: true // 冻结表名,不自动复数化
    }
  }
);

module.exports = sequelize;

连接参数说明

| 参数 | 说明 | 默认值 | |------|------|--------| | host | 服务器地址 | 127.0.0.1 | | port | 端口号 | 5138 | | dialect | 数据库方言 | mysql(已替换为 xugu-dialect) | | logging | 是否记录 SQL 日志 | false | | pool.max | 最大连接数 | 20 | | pool.min | 最小连接数 | 5 | | pool.acquire | 获取连接超时时间(毫秒) | 30000 | | pool.idle | 连接空闲超时时间(毫秒) | 10000 | | define.timestamps | 是否自动添加时间戳字段 | true | | define.underscored | 是否使用下划线命名法 | false | | define.freezeTableName | 是否冻结表名 | false |

第三步:定义模型

基本模型定义

创建 models/user.js 文件:

const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');

const User = sequelize.define('User', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
    comment: '用户ID'
  },
  username: {
    type: DataTypes.STRING(50),
    allowNull: false,
    unique: true,
    comment: '用户名'
  },
  email: {
    type: DataTypes.STRING(100),
    allowNull: false,
    unique: true,
    validate: {
      isEmail: true
    },
    comment: '邮箱'
  },
  age: {
    type: DataTypes.INTEGER,
    defaultValue: 0,
    validate: {
      min: 0,
      max: 150
    },
    comment: '年龄'
  },
  isActive: {
    type: DataTypes.BOOLEAN,
    defaultValue: true,
    comment: '是否活跃'
  },
  createdAt: {
    type: DataTypes.DATE,
    allowNull: false,
    defaultValue: DataTypes.NOW,
    comment: '创建时间'
  },
  updatedAt: {
    type: DataTypes.DATE,
    allowNull: false,
    defaultValue: DataTypes.NOW,
    comment: '更新时间'
  }
}, {
  tableName: 'users', // 指定表名
  timestamps: true,   // 自动管理 createdAt 和 updatedAt 字段
  paranoid: true,     // 启用软删除(添加 deletedAt 字段)
  comment: '用户表'
});

module.exports = User;

字段类型说明

| 字段类型 | 说明 | 示例 | |----------|------|------| | DataTypes.INTEGER | 整数 | DataTypes.INTEGER | | DataTypes.BIGINT | 大整数 | DataTypes.BIGINT | | DataTypes.STRING | 字符串 | DataTypes.STRING(100) | | DataTypes.TEXT | 文本 | DataTypes.TEXT | | DataTypes.FLOAT | 浮点数 | DataTypes.FLOAT | | DataTypes.DOUBLE | 双精度浮点数 | DataTypes.DOUBLE | | DataTypes.DECIMAL | 十进制数 | DataTypes.DECIMAL(10, 2) | | DataTypes.BOOLEAN | 布尔值 | DataTypes.BOOLEAN | | DataTypes.DATE | 日期时间 | DataTypes.DATE | | DataTypes.DATEONLY | 日期 | DataTypes.DATEONLY | | DataTypes.TIME | 时间 | DataTypes.TIME | | DataTypes.UUID | UUID | DataTypes.UUID | | DataTypes.JSON | JSON | DataTypes.JSON | | DataTypes.BLOB | 二进制大对象 | DataTypes.BLOB |

关联关系

创建 models/article.js 文件:

const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const User = require('./user');

const Article = sequelize.define('Article', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
    comment: '文章ID'
  },
  title: {
    type: DataTypes.STRING(200),
    allowNull: false,
    comment: '标题'
  },
  content: {
    type: DataTypes.TEXT,
    comment: '内容'
  },
  userId: {
    type: DataTypes.INTEGER,
    allowNull: false,
    comment: '作者ID'
  }
}, {
  tableName: 'articles',
  timestamps: true,
  comment: '文章表'
});

// 定义关联关系
Article.belongsTo(User, { foreignKey: 'userId', as: 'author' });
User.hasMany(Article, { foreignKey: 'userId', as: 'articles' });

module.exports = Article;

创建 models/tag.js 文件:

const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Article = require('./article');

const Tag = sequelize.define('Tag', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
    comment: '标签ID'
  },
  name: {
    type: DataTypes.STRING(50),
    allowNull: false,
    unique: true,
    comment: '标签名'
  }
}, {
  tableName: 'tags',
  timestamps: true,
  comment: '标签表'
});

// 定义多对多关系
const ArticleTag = sequelize.define('ArticleTag', {
  articleId: {
    type: DataTypes.INTEGER,
    allowNull: false,
    comment: '文章ID'
  },
  tagId: {
    type: DataTypes.INTEGER,
    allowNull: false,
    comment: '标签ID'
  }
}, {
  tableName: 'article_tags',
  timestamps: false,
  comment: '文章标签关联表'
});

Article.belongsToMany(Tag, { through: ArticleTag, foreignKey: 'articleId', as: 'tags' });
Tag.belongsToMany(Article, { through: ArticleTag, foreignKey: 'tagId', as: 'articles' });

module.exports = { Tag, ArticleTag };

第四步:数据库迁移

创建迁移文件

# 初始化 Sequelize CLI
npx sequelize-cli init

# 创建迁移文件
npx sequelize-cli migration:generate --name create-users
npx sequelize-cli migration:generate --name create-articles
npx sequelize-cli migration:generate --name create-tags

迁移文件示例

创建 migrations/xxxx-create-users.js 文件:

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      username: {
        type: Sequelize.STRING(50),
        allowNull: false,
        unique: true
      },
      email: {
        type: Sequelize.STRING(100),
        allowNull: false,
        unique: true
      },
      age: {
        type: Sequelize.INTEGER,
        defaultValue: 0
      },
      is_active: {
        type: Sequelize.BOOLEAN,
        defaultValue: true
      },
      created_at: {
        allowNull: false,
        type: Sequelize.DATE,
        defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
      },
      updated_at: {
        allowNull: false,
        type: Sequelize.DATE,
        defaultValue: Sequelize.literal('CURRENT_TIMESTAMP')
      },
      deleted_at: {
        type: Sequelize.DATE
      }
    });

    // 添加索引
    await queryInterface.addIndex('users', ['username']);
    await queryInterface.addIndex('users', ['email']);
    await queryInterface.addIndex('users', ['is_active']);
  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('users');
  }
};

执行迁移

# 执行所有迁移
npx sequelize-cli db:migrate

# 回滚迁移
npx sequelize-cli db:migrate:undo

# 回滚所有迁移
npx sequelize-cli db:migrate:undo:all

第五步:CRUD 操作

创建记录

const User = require('./models/user');

// 创建单个记录
async function createUser(userData) {
  try {
    const user = await User.create(userData);
    console.log('Created user:', user.toJSON());
    return user;
  } catch (error) {
    console.error('Error creating user:', error);
    throw error;
  }
}

// 批量创建
async function createUsers(usersData) {
  try {
    const users = await User.bulkCreate(usersData);
    console.log('Created users:', users.map(u => u.toJSON()));
    return users;
  } catch (error) {
    console.error('Error creating users:', error);
    throw error;
  }
}

// 使用示例
createUser({
  username: 'john',
  email: 'john@example.com',
  age: 25
});

createUsers([
  { username: 'user1', email: 'user1@example.com', age: 20 },
  { username: 'user2', email: 'user2@example.com', age: 25 },
  { username: 'user3', email: 'user3@example.com', age: 30 }
]);

查询记录

// 查询所有记录
async function getAllUsers() {
  try {
    const users = await User.findAll();
    console.log('All users:', users.map(u => u.toJSON()));
    return users;
  } catch (error) {
    console.error('Error fetching users:', error);
    throw error;
  }
}

// 查询单个记录
async function getUserById(id) {
  try {
    const user = await User.findByPk(id);
    if (user) {
      console.log('User found:', user.toJSON());
    } else {
      console.log('User not found');
    }
    return user;
  } catch (error) {
    console.error('Error fetching user:', error);
    throw error;
  }
}

// 条件查询
async function getUsersByAge(age) {
  try {
    const users = await User.findAll({
      where: {
        age: age,
        isActive: true
      },
      order: [['createdAt', 'DESC']],
      limit: 10,
      offset: 0
    });
    console.log('Users found:', users.map(u => u.toJSON()));
    return users;
  } catch (error) {
    console.error('Error fetching users:', error);
    throw error;
  }
}

// 复杂查询
async function searchUsers(keyword) {
  try {
    const { Op } = require('sequelize');
    const users = await User.findAll({
      where: {
        [Op.or]: [
          { username: { [Op.like]: `%${keyword}%` } },
          { email: { [Op.like]: `%${keyword}%` } }
        ]
      },
      attributes: ['id', 'username', 'email', 'age'],
      include: [{
        model: Article,
        as: 'articles',
        attributes: ['id', 'title']
      }]
    });
    console.log('Search results:', users.map(u => u.toJSON()));
    return users;
  } catch (error) {
    console.error('Error searching users:', error);
    throw error;
  }
}

更新记录

// 更新单个记录
async function updateUser(id, updateData) {
  try {
    const user = await User.findByPk(id);
    if (!user) {
      console.log('User not found');
      return null;
    }
    
    await user.update(updateData);
    console.log('Updated user:', user.toJSON());
    return user;
  } catch (error) {
    console.error('Error updating user:', error);
    throw error;
  }
}

// 批量更新
async function updateUsersAge(age, newAge) {
  try {
    const [affectedCount] = await User.update(
      { age: newAge },
      {
        where: {
          age: age,
          isActive: true
        }
      }
    );
    console.log('Updated users count:', affectedCount);
    return affectedCount;
  } catch (error) {
    console.error('Error updating users:', error);
    throw error;
  }
}

删除记录

// 删除单个记录(软删除)
async function deleteUser(id) {
  try {
    const user = await User.findByPk(id);
    if (!user) {
      console.log('User not found');
      return false;
    }
    
    await user.destroy();
    console.log('Deleted user:', user.toJSON());
    return true;
  } catch (error) {
    console.error('Error deleting user:', error);
    throw error;
  }
}

// 批量删除(软删除)
async function deleteInactiveUsers() {
  try {
    const affectedCount = await User.destroy({
      where: {
        isActive: false
      }
    });
    console.log('Deleted users count:', affectedCount);
    return affectedCount;
  } catch (error) {
    console.error('Error deleting users:', error);
    throw error;
  }
}

// 物理删除
async function permanentDeleteUser(id) {
  try {
    const user = await User.findByPk(id, { paranoid: false });
    if (!user) {
      console.log('User not found');
      return false;
    }
    
    await user.destroy({ force: true });
    console.log('Permanently deleted user:', user.toJSON());
    return true;
  } catch (error) {
    console.error('Error permanently deleting user:', error);
    throw error;
  }
}

第六步:事务处理

基本事务

async function transferMoney(fromUserId, toUserId, amount) {
  const transaction = await sequelize.transaction();
  
  try {
    // 从发送方扣款
    const fromUser = await User.findByPk(fromUserId, { transaction });
    if (!fromUser || fromUser.balance  {
      // 创建用户
      const user = await User.create(userData, { transaction: t });
      
      // 创建用户资料
      const profile = await Profile.create({
        ...profileData,
        userId: user.id
      }, { transaction: t });
      
      return { user, profile };
    });
    
    console.log('Created user with profile:', result);
    return result;
  } catch (error) {
    console.error('Error creating user with profile:', error);
    throw error;
  }
}

第七步:性能优化

批量操作

// 批量插入
async function bulkCreateUsers(usersData) {
  try {
    const users = await User.bulkCreate(usersData, {
      validate: true,
      ignoreDuplicates: true
    });
    console.log('Bulk created users:', users.length);
    return users;
  } catch (error) {
    console.error('Error bulk creating users:', error);
    throw error;
  }
}

// 分批插入
async function bulkCreateUsersInBatches(usersData, batchSize = 100) {
  try {
    const results = [];
    for (let i = 0; i  {
  beforeEach(async () => {
    await User.destroy({ where: {}, force: true });
  });
  
  it('should create a user', async () => {
    const user = await User.create({
      username: 'testuser',
      email: 'test@example.com',
      age: 25
    });
    
    expect(user).to.have.property('id');
    expect(user.username).to.equal('testuser');
    expect(user.email).to.equal('test@example.com');
    expect(user.age).to.equal(25);
  });
  
  it('should find a user by id', async () => {
    const user = await User.create({
      username: 'testuser',
      email: 'test@example.com',
      age: 25
    });
    
    const foundUser = await User.findByPk(user.id);
    expect(foundUser).to.not.be.null;
    expect(foundUser.username).to.equal('testuser');
  });
  
  it('should update a user', async () => {
    const user = await User.create({
      username: 'testuser',
      email: 'test@example.com',
      age: 25
    });
    
    await user.update({ age: 26 });
    expect(user.age).to.equal(26);
  });
  
  it('should delete a user', async () => {
    const user = await User.create({
      username: 'testuser',
      email: 'test@example.com',
      age: 25
    });
    
    await user.destroy();
    const foundUser = await User.findByPk(user.id);
    expect(foundUser).to.be.null;
  });
});

验证数据库连接

// 验证数据库连接
async function testConnection() {
  try {
    await sequelize.authenticate();
    console.log('Database connection has been established successfully.');
    return true;
  } catch (error) {
    console.error('Unable to connect to the database:', error);
    return false;
  }
}

// 验证表结构
async function testTableStructure() {
  try {
    const tableInfo = await sequelize.getQueryInterface

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [kourou25](https://github.com/kourou25)
- **Source:** [kourou25/xugudb-dev-skills](https://github.com/kourou25/xugudb-dev-skills)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.