04 NodeJs访问MySql 数据库

在NodeJs中访问Mysql数据库

一、MySql数据库中访问数据库形式:

在Node.js中访问MySQL数据库有多种形式,以下是其中的一些常见方式:

  1. 原生MySQL驱动:使用Node.js的原生MySQL驱动来连接和操作数据库。这是最早的方式,但在许多现代应用中,由于其复杂性,它可能不是首选。
  2. Sequelize ORM:Sequelize是一个流行的Node.js ORM(对象关系映射)库,它允许你使用JavaScript对象来操作数据库。通过定义模型和它们之间的关系,你可以方便地进行CRUD操作。
  3. TypeORM:这是另一个流行的Node.js ORM,与Sequelize类似,但有一些不同的特性和用法。
  4. Query Builder :一些库如knex提供了一个查询构建器,允许你以链式方式构建复杂的数据库查询。
  5. Adapters :对于一些框架(如Express),有专门的数据库适配器,如express-mysql-session,它为Express应用提供了MySQL会话存储。
  6. ORM-Drivers:一些ORM(如TypeORM)有自己的数据库驱动,这些驱动通常提供与特定数据库的连接和操作功能。
  7. GraphQL:GraphQL与MySQL结合使用时,你可以定义数据模型和查询,然后使用GraphQL服务器从MySQL数据库检索数据。
  8. ORM-Generators:有些工具可以自动生成基于数据库结构的Node.js代码,例如TypeScript类和模型。
  9. 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 小结

  1. 无论使用数据库连接池 还是直接使用数据库连接其数据库操作代码只有取得连接时有差异,其它部分均相同;
  2. 当执行的SQL语句中需参数时,在SQL语句需要参数位置以?(问题)进行占位,然后再将参数按顺序添加到后面。
相关推荐
2401_857610036 分钟前
Spring Boot框架:电商系统的技术优势
java·spring boot·后端
杨哥带你写代码2 小时前
网上商城系统:Spring Boot框架的实现
java·spring boot·后端
camellias_2 小时前
SpringBoot(二十一)SpringBoot自定义CURL请求类
java·spring boot·后端
背水2 小时前
初识Spring
java·后端·spring
晴天飛 雪3 小时前
Spring Boot MySQL 分库分表
spring boot·后端·mysql
weixin_537590453 小时前
《Spring boot从入门到实战》第七章习题答案
数据库·spring boot·后端
AskHarries3 小时前
Spring Cloud Gateway快速入门Demo
java·后端·spring cloud
Qi妙代码3 小时前
MyBatisPlus(Spring Boot版)的基本使用
java·spring boot·后端
宇宙超级勇猛无敌暴龙战神4 小时前
Springboot整合xxl-job
java·spring boot·后端·xxl-job·定时任务