Skip to content

数据库

简介

项目使用 mysql2 来处理 MySQL 数据库交互。系统提供两个模块来和数据库交互。

简单的例子

这是一个简单的例子。

javascript

const dbUtil = require('./utils/db.js');

const connection = dbUtil.getConnection();

// 一个简单查询
try {
  const [results, fields] = await connection.query(
    'SELECT * FROM `table` WHERE `name` = "Page" AND `age` > 45'
  );

  console.log(results); // results contains rows returned by server
  console.log(fields); // fields contains extra meta data about results, if available
} catch (err) {
  console.log(err);
}

// 使用占位符
try {
  const [results] = await connection.query(
    'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
    ['Page', 45]
  );

  console.log(results);
} catch (err) {
  console.log(err);
}

使用预处理语句

以上都是使用 connection.query(),使用 connection.execute()可以完成 SQL 语句的预处理,以防止 SQL 注入的安全问题。

javascript
const dbUtil = require('./utils/db.js');

try {
  // create the connection to database
  const connection = dbUtil.getConnection();

  // execute will internally call prepare and query
  const [results, fields] = await connection.execute(
    'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
    ['Rick C-137', 53]
  );

  console.log(results); // results contains rows returned by server
  console.log(fields); // fields contains extra meta data about results, if available
} catch (err) {
  console.log(err);
}

关闭数据库连接

js
connection.end()

使用数据库连接池

使用数据库连接池,可以与 connection 相同的方式使用池(使用pool.query() 和 pool.execute() ):

javascript
const dbUtil = require('./utils/db.js');

try {
  const [rows, fields] = await dbUtil.query('SELECT `field` FROM `table`');
  // 查询解析厚,连接会自动释放到连接池
} catch (err) {
  console.log(err);
}

手动操作数据库连接池

当然,也可以从池中手动获取连接并稍后返回:

javascript
const dbUtil = require('./utils/db.js');

const connection = await dbUtil.getConnection();

await connection.query(/* ... */);

await connection.release();

注意:手动获取数据库连接,就必须手动释放。否则程序会崩溃。推荐把 connection.release() 放在 try catch 的 finally 中执行。

javascript
const dbUtil = require('./utils/db.js');

try {
  const connection = await dbUtil.getConnection();
  await connection.query(/* ... */);
} catch(e) {
  console.log(e);
} finally {
  connection.release()
}

命名占位符 通过设置 namedPlaceholders 配置值可以为参数使用命名占位符。

javascript
connection.config.namedPlaceholders = true;

connection.execute('select :x + :y as z', { x: 1, y: 2 }, (err, rows) => {
  // statement prepared as "select ? + ? as z" and executed with [1,2] values
  // rows returned: [ { z: 3 } ]
});

connection.execute('select :x + :x as z', { x: 1 }, (err, rows) => {
  // select ? + ? as z, execute with [1, 1]
});

connection.query('select :x + :x as z', { x: 1 }, (err, rows) => {
  // query select 1 + 1 as z
});

// unnamed placeholders are still valid if the values are provided in an array
connection.query('select ? + ? as z', [1, 1], (err, rows) => {
  // query select 1 + 1 as z
});

错误处理

确保对查询操作进行适当的错误处理,无论是使用回调还是 async/await。

释放连接

使用连接池时,你不需要手动释放每个连接,因为查询结束后,连接会自动返回到池中。但是,如果在查询之外还需要进行其他操作(如事务),确保在操作完成后调用 connection.release() 来释放连接。

性能调优

根据实际需求调整连接池的参数,比如 connectionLimit,以达到最佳性能。监控应用和数据库性能,适时调整连接池设置,以应对不同的负载情况。

通过上述步骤,你可以有效地在 Node.js 应用中利用 mysql2 的连接池功能来管理数据库连接,提升应用性能和稳定性。

助手函数

系统提供了六个助手函数

  • findOne()
  • findAll()
  • findCounter()
  • save()
  • update()
  • destroy()

findOne()

获取一条记录

javascript
let one, obj;

// 获取id是19的记录
one = await dbUtil.findOne('tb_page', 19);
console.log('one',one)

// 获取一条记录
obj = {
  where:{is_show:0,user_id:1},
};
one = await dbUtil.findOne('tb_page',obj);
console.log('one',one)

// 按条件获取一条记录
obj = {
  where:{is_show:0},
  order:{id:'asc'},
  limit:2,
  offset:1
};
one = await dbUtil.findOne('tb_page',obj);
console.log('one',one)

findAll()

获取一组记录

javascript
let rows, obj;

// 按条件获取多行条记录
obj = {
  where:{is_show:0},
  order:{id:'asc'},
  limit:2,
  offset:1
};
rows = await dbUtil.findAll('tb_page',obj);
console.log('one',one)

findCounter()

获取记录数量

javascript
let rows, obj;

// 按条件获取多记录总数
obj = {
  where:{is_show:0}
};
rows = await dbUtil.findAll('tb_page',obj);
console.log('one',one)

save()

保存一条记录

javascript
let data = {
  title:'这是标题',
  user_id:1,
  content:'这是内容'
};
let result = await dbUtil.save('tb_page',data);
console.log('res',result)

/* 返回结果
ResultSetHeader {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 27,
  info: '',
  serverStatus: 2,
  warningStatus: 0,
  changedRows: 0
}
*/

update()

更新记录。会忽略 data.id

javascript
let data = {
  id:200,
  title:'这是标题', 
  user_id:1, 
  content:'这是内容'
};

let obj = {
  where:{
    id:28,
    is_show:1
  }
};

let result = await dbUtil.update('tb_page', data, obj);
console.log('res',result)

destroy()

删除记录。

javascript
let obj = {
  where:{
    user_id:2
  }
};
let result = await dbUtil.destroy('tb_page', obj);

DAO(即将废弃)

在系统的 ./utils/dao.js 中,有一组常用的方法。

javascript
const Dao = require("./utils/dao.js");

try {
  const pageDao = new Dao();
  pageDao.setTable('tb_page'); // 设置Dao关联的表

  let page, data, where, result, counter;

  // 获取一条记录,记录的id是12
  page = await pageDao.findOne(12);

  // 获取多条记录
  where = {is_show:1};
  // 相当于执行`SELECT * FROM tb_page WHERE is_show=1`
  result = await pageDao.findAll({where:where});

  // 获取符合条件的记录数量
  counter = await pageDao.findAllCounter({where:where});

  // 保存一个对象到表中
  data = { title:"这是标题", content:"这是内容"};
  result = await pageDao.save(data);

  // 更新一个对象到表中
  data = { title:"这是标题", content:"这是内容", id:12};
  result = await pageDao.update(data);

  // 删除一条记录
  where = {id:12, is_show:1};
  result = await pageDao.delete({where:where});

  // 其他操作
} catch(error) {
  // 其他操作
}

参考