@lct/common
Version:
287 lines (267 loc) • 11.6 kB
text/typescript
/// <reference path="../typings/index.d.ts" />
import BaseModel from "../model/base";
import modelHelper from "./modelHelper";
/**
* 提供DB操作基础库
* 支持分页等功能
*/
class DBHelper {
/**
* 生成DB实例
* @param db DB操作对象,mysql的connection或 eggjs的
*/
constructor(db: any = null) {
this.db = db;
}
/**
* DB操作对象,
* 可以是原生的mysql连接,或eggjs的
*/
public db: any;
/**
* 使用query,可用来查询或SQL执行
* @param {IDBQueryParam} pars 执行参数,
* 1. 如果有sql属性,则只有sql和params有效。params为sql中的?参数, 例如 `{"sql": "select * from table where id=? and title like ?", params: [1, '%abc%']}`
* 2. 如果有where且为string, 则会拼接sql执行 where 会拼到sql的where关健词后面。如:`{table: 'table1', where: 'id=? or title=?', columns: 'id,title',orders: [['time', 'desc']]}`
* 结果会拼成: `select id, title from table1 where id=? or title=? order by time desc`
* 3. 如果where为object, 则会直接调用db的select
* @param {BaseModel} [optional] 可选参数,如果指定了具体的model类,则会实例化成model的数组对象返回
* @returns {IDBResult}
*/
async query(pars: IDBQueryParam, type?: { new(): BaseModel}|any): Promise<IDBResult> {
let result = {
data: new Array<any>()
};
pars.columns = pars.columns || '*';
pars.db = pars.db || this.db;
if(type && !pars.table) pars.table = type._tableName;
if(pars.sql) {
result.data = await this.execute(pars);
}
//where为字符串的情况,则拼sql来执行
else if(pars.where && typeof pars.where == 'string') {
result.data = await this.queryStringWhere(pars);
}
//where为object情况,直接select
else if(pars.where && typeof pars.where == 'object') {
result.data = await this.select(pars, type);
}
//如果指定了需要的类型,则先转换
if(result.data && result.data.length && type) {
result.data = modelHelper.toArray(result.data, type);
}
return result;
}
/**
* 执行SQL
* @param pars SQL和执行参数。如:{sql: 'update table set title=? where id=?', params: ['title1', 1]}
* @returns {any} 受影响的行数
*/
async execute(pars: IDBSqlParam): Promise<any> {
return this.executeSql(pars.sql || '', pars.params, pars.db || this.db);
}
/**
* 执行有where并且为字符串的情况
* 此函数不支持属性名到字段的映射,调用前自已处理
* @param pars
*/
async queryStringWhere(pars: IDBQueryParam): Promise<any> {
//如果是数组,则做一次字段映射,并转为字符串
let columns = pars.columns || '*';
let sql = `select ${columns} from ${pars.table}`;
if(pars.where) sql += ` where ${pars.where}`;
//拼接排序字段
if(pars.orders && pars.orders.length) {
let ordersql = '';
pars.orders.forEach((p)=> {
if(ordersql) ordersql += ',';
ordersql += p.join(' ');
});
sql += ' order by ' + ordersql;
}
//如果有条数限制
if(pars.limit) {
if(pars.offset) {
sql += ` limit ${pars.offset},${pars.limit}`;
}
else {
sql += ` limit ${pars.limit}`;
}
}
return this.executeSql(sql, pars.params, pars.db||this.db);
}
/**
* 获取单个数据
* @param pars 获取单条数据接口,{table:'table1', where: {id:1}}
*/
async get(pars: IDBQueryParam, type?: { new(): BaseModel}|any): Promise<any> {
if(type && !pars.table) pars.table = type._tableName;
pars.db = pars.db || this.db;
if(pars.db.get) {
//如果有传类型,则会做一次属性到字段的映射
let where = type? modelHelper.objectToFieldValues(pars.where, type): pars.where;
let data = await pars.db.get(pars.table, where);
if(type) data = new type(data);
return data;
}
else {
//如果是数组,则做一次字段映射,并转为字符串
let columns = pars.columns || '*';
if(Array.isArray(columns)) {
columns = modelHelper.convertFields(columns, type).join(',');
}
let sql = `SELECT ${columns} FROM ${pars.table}`;
let where = modelHelper.createSqlWhere(pars.where);
if(where.where) {
sql += ' WHERE ' + where.where;
}
let data = await this.executeSql(sql, where.params, pars.db);
if(data && data.length) {
data = type? new type(data[0]): data[0];
}
return data;
}
}
/**
* 当where为object时,采用select直接查
* @param pars select参数,where为object情况
*/
async select(pars: IDBQueryParam, type: {new():BaseModel, _fieldMap: object;}|BaseModel): Promise<any> {
pars.db = pars.db || this.db;
//如果是数组,则做一次字段映射,并转为字符串
let columns = pars.columns || '*';
if(Array.isArray(columns)) {
columns = modelHelper.convertFields(columns, type).join(',');
}
//如果是eggjs这种提供了select的,则直接调用,否则调用mysql原接口
if(pars.db.select) {
let condition = {
where: pars.where,
orders: pars.orders || [],
columns: columns,
limit: pars.limit,
offset: pars.offset
};
return await pars.db.select(pars.table, condition);
}
else {
let where = modelHelper.createSqlWhere(pars.where);
return await this.queryStringWhere({
db: pars.db,
table: pars.table,
where: where.where,
params: where.params,
orders: pars.orders || [],
columns: columns,
limit: pars.limit,
offset: pars.offset
});
}
}
/**
* 更新数据
* 指定table 和 where 即可。如:{table: 'table1', where: {id:1}}
* @param pars {BaseModel|IDBOperationParam} 需要更新model对象,或操作指定
* @param table {String}[optinal] 表名,如果不指定则从pars中读
* @param db {any}[optional] 当前DB连接,不指定则用当前实例DB
*/
async update(pars: IDBOperationParam|BaseModel, table?: string, db?: any): Promise<IDBExecuteResult> {
db = (pars instanceof BaseModel? db: pars.db) || this.db;
table = table || (pars instanceof BaseModel? pars._tableName: pars.table);
let data = pars instanceof BaseModel? pars._dbData: pars.data;
//生成更新主健
let primaryWhere = pars instanceof BaseModel? modelHelper.getPrimaryKeysWhere(pars): pars.where;
if(db.update) {
return await db.update(table, data, primaryWhere);
}
else {
let sql = `UPDATE ${table} SET `;
let params = new Array<any>();
for(let c in data) {
//如果是主健,则不参与更新
if(primaryWhere[c] || typeof c != 'string') continue;
sql += ` \`${c}\` = ?,`;
params.push(data[c]);
}
if(sql.endsWith(',')) sql = sql.replace(/,$/, '');
//组合更新条件
let where = modelHelper.createSqlWhere(primaryWhere, pars instanceof BaseModel? pars: undefined);
if(where.where) {
sql += ' WHERE ' + where.where;
params = params.concat(where.params);
}
return await this.executeSql(sql, params, db);
}
}
/**
* 删除数据
* 指定table 和 where 即可。如:{table: 'table1', where: {id:1}}
* @param pars {BaseModel|IDBOperationParam} 需要更新model对象,或操作指定
* @param table {String}[optinal] 表名,如果不指定则从pars中读
* @param db {any}[optional] 当前DB连接,不指定则用当前实例DB
*/
async delete(pars: IDBOperationParam|BaseModel, table?: string, db?: any): Promise<IDBExecuteResult> {
db = (pars instanceof BaseModel? db: pars.db) || this.db;
table = table || (pars instanceof BaseModel? pars._tableName: pars.table);
//生成删除主健
let primaryWhere = pars instanceof BaseModel? modelHelper.getPrimaryKeysWhere(pars): pars.where;
if(db.delete) {
return db.delete(table, primaryWhere);
}
else {
let sql = `DELETE FROM ${table}`;
let params = new Array<any>();
//组合更新条件
let where = modelHelper.createSqlWhere(primaryWhere, pars instanceof BaseModel? pars: undefined);
if(where.where) {
sql += ' WHERE ' + where.where;
params = params.concat(where.params);
}
else {
throw "未指定删除条件";
}
return await this.executeSql(sql, params, db);
}
}
/**
* 往DB里插入一个model对象
* @param data {BaseModel|IDBOperationParam} 新增的数据model或操作选项
* @param table {string} 表名
* @param db {MySql.Connection}[optional] DB连接
* @returns {fieldCount: 0,affectedRows: 1,insertId: 6,serverStatus: 2,warningCount: 0,message: '',protocol41: true,changedRows: 0 }
*/
async insert(data: IDBOperationParam|BaseModel, table: string = "", db: any = null): Promise<any> {
//如果是IDBOperationParam,则调用eggjs相关接口
if(data && data instanceof BaseModel) {
table = table || data._tableName;
db = db || this.db;
let sql = `INSERT INTO ${table} SET ?`;
return this.executeSql(sql, data._dbData, db);
}
else if(data.db) {
return data.db.insert(table||data.table, data.data);
}
}
/**
* 执行sql
* @param sql 要执行的SQL 例如sql="select * from id=?"
* @param params SQL中的参数,例如[1]
* @param db DB连接
*/
async executeSql(sql: string, params: any=[], db: any=null): Promise<any> {
db = db || this.db;
return new Promise((resolve, reject) => {
let qry = db.query(sql, params, (err, results)=>{
if(err) {
if(reject) reject(err);
else throw err;
}
else {
resolve && resolve(results);
}
});
qry && qry.sql && console.log(qry.sql);
});
}
}
export default DBHelper;