在NodeJs中访问Mysql数据库
一、MySql数据库中访问数据库形式:
在Node.js中访问MySQL数据库有多种形式,以下是其中的一些常见方式:
- 原生MySQL驱动:使用Node.js的原生MySQL驱动来连接和操作数据库。这是最早的方式,但在许多现代应用中,由于其复杂性,它可能不是首选。
- Sequelize ORM:Sequelize是一个流行的Node.js ORM(对象关系映射)库,它允许你使用JavaScript对象来操作数据库。通过定义模型和它们之间的关系,你可以方便地进行CRUD操作。
- TypeORM:这是另一个流行的Node.js ORM,与Sequelize类似,但有一些不同的特性和用法。
- Query Builder :一些库如
knex
提供了一个查询构建器,允许你以链式方式构建复杂的数据库查询。 - Adapters :对于一些框架(如Express),有专门的数据库适配器,如
express-mysql-session
,它为Express应用提供了MySQL会话存储。 - ORM-Drivers:一些ORM(如TypeORM)有自己的数据库驱动,这些驱动通常提供与特定数据库的连接和操作功能。
- GraphQL:GraphQL与MySQL结合使用时,你可以定义数据模型和查询,然后使用GraphQL服务器从MySQL数据库检索数据。
- ORM-Generators:有些工具可以自动生成基于数据库结构的Node.js代码,例如TypeScript类和模型。
- Native Bindings:对于某些数据库,可能有Node.js的native bindings可用,这些bindings直接与数据库的API交互,可能比纯JavaScript实现更快。
二、原生MySQL驱动访问方法
原生MySQL驱动通过执行SQL语句对数据库进行查询、修改等操作,其需要熟悉SQL语法,复杂度随SQL语句的复杂度而变化;然而原生MySQL驱动访问方法的好处有以下几点: a. 灵活性和控制力 :原生MySQL驱动允许开发者直接与MySQL数据库交互,可以执行任何有效的SQL查询,提供了最大程度的灵活性和控制力。 b. 性能 :由于它直接与MySQL数据库交互,因此在某些情况下,原生驱动可能会比其他封装层提供更好的性能。 c. 简单易用 :对于简单的查询和操作,原生驱动提供了简洁的API,使得读写数据变得相对容易。 d. 社区支持 :由于原生MySQL驱动是Node.js官方支持的数据库驱动之一,它拥有庞大的社区和丰富的资源,遇到问题时可以获得大量的帮助和解决方案。 e. 跨平台性:原生MySQL驱动可以在任何支持Node.js的平台上运行,具有很好的跨平台性。
1. 操作流程
graph TD
A[创建数据库连接] --> B[访问数据库]
B --> C1[执行查询语句]
C1 --> D1[解析查询结果]
D1 --> E[关闭数据库连接]
B --> C2[执行修改语句]
C2 --> D2[解析执行结果]
D2 --> E[关闭数据库连接]
在访问数据库前首先需要创建NodeJs与Mysql数据库的连接,之后再通过该连接来访问数据库;在创建数据库连接时有两种形式: 直接创建数据库连接 ,通过指定数据信息,直接创建一个连接,用完后关闭连接; 以数据库连接池 的形式,在程序开始前创建数据库连接池,当需要访问数据库时从连接池 中获取一个连接 ,用完返还给连接池 ;通过连接池规避了每次创建数据库连接的时间开支,同时也避免了程序因创建大量数据库链接造成的资源消耗。
2.代码实现
首先安装NodeJs访问Mysql数据库的组件:mysql
javascript
npm install mysql
2.1 以连接的形式访问数据库
javascript
//通过回调模拟同步执行
const mysql = require('mysql');
// 创建连接配置
const connectionConfig = {
host: 'localhost',
user: 'root',
password: '123456',
database: 'video_site',
debug: false // 开启调试模式,会输出详细的SQL执行日志
};
// 获取用户信息的同步函数(实际上内部仍然是异步的)
function getUserInfoSync(callback) {
// 创建新的连接
const connection = mysql.createConnection(connectionConfig);
// 连接到数据库
connection.connect((error) => {
if (error) {
callback(error, null);
return;
}
// 执行查询
connection.query('SELECT * FROM users', (error, results) => {
// 关闭连接
connection.end();
if (error) {
callback(error, null);
} else {
callback(null, results);
}
});
});
}
// 主函数
function main() {
getUserInfoSync((error, userInfo) => {
if (error) {
console.error('Error retrieving user:', error);
} else {
console.log('User Info:', userInfo);
for( i = 0; i < userInfo.length; ++i)
{
console.log('User Info:', userInfo[i]);
}
}
});
}
// 调用主函数
main();
//输出
User Info: (3) [RowDataPacket, RowDataPacket, RowDataPacket]
DBTest.js:90
User Info: RowDataPacket {ID: 1, UserName: 'u1', Email: 'e1', Pwd: '123', Tel: '12345678901', ...}
DBTest.js:93
User Info: RowDataPacket {ID: 2, UserName: 'u2', Email: 'e2', Pwd: '12345', Tel: '12345678', ...}
DBTest.js:93
User Info: RowDataPacket {ID: 3, UserName: 'u3', Email: 'e3', Pwd: '123456', Tel: '1234567', ...}
2.2 以连接池的形式访问数据库
下面示例中所有函数均为异步函数
javascript
const mysql = require('mysql');
const connectionConfig = {
connectionLimit: 10, // 连接池最大连接数
host: 'localhost',
user: 'root',
password: '123456',
database: 'video_site',
debug: false // 开启调试模式,会输出详细的SQL执行日志
};
// 查询数据库的示例函数
function getUserInfo(id) {
// 创建一个连接池
const pool = mysql.createPool(connectionConfig);
// 从连接池中获取连接
pool.getConnection((err, connection) => {
if (err) {
if (err.code === 'PROTOCOL_CONNECTION_LOST') {
console.error('Database connection was closed.')
}
if (err.code === 'ER_CON_COUNT_ERROR') {
console.error('Database has too many connections.')
}
if (err.code === 'ECONNREFUSED') {
console.error('Database connection was refused.')
}
}
if (connection) {
// 执行查询
connection.query('SELECT * FROM users where id = ?', [id],(error, results, fields) => {
// 查询完成后,释放连接
connection.release();
if (error) {
console.error('Query error:', error);
return;
}
// 输出查询结果
console.log('Query results:', results);
});
}
});
}
id = 1;
// 调用示例函数
getUserInfo(id);
//输出结果
User Info: (1) [RowDataPacket]
DBTest2.js:43
arg1:
(1) [RowDataPacket]
0:
RowDataPacket {ID: 1, UserName: 'u1', Email: 'e1', Pwd: '123', Tel: '12345678901', ...}
length:
1
[[Prototype]]:
Array(0)
[[Prototype]]:
Object
2.3 小结
- 无论使用数据库连接池 还是直接使用数据库连接其数据库操作代码只有取得连接时有差异,其它部分均相同;
- 当执行的SQL语句中需参数时,在SQL语句需要参数位置以?(问题)进行占位,然后再将参数按顺序添加到后面。