学习nodejs mysql的一些心得

69 阅读1分钟

闲话少说,直接开启第二弹 相较于昨日,更改了一些bug,之前都是在公司写的,回家懒得测试 今天更新了一些bug,然后完成了自动填充注解 话不多b,直接看代码

export function fieldFill(type: ("DEFAULT" | "INSERT" | "UPDATE" | "INSERT_UPDATE")) {
  return (target: any, name: string) => {
    let className = "";
    store.classNameArr.forEach(item => {
      if (item[target.constructor.name]) {
        className = item[target.constructor.name];
      }
    })
    className = className || target.constructor.name; //存储的是表名,如果有自定义表名就是自定义表名,没有就是类名
    let a = false;
    store.classFieldFill.forEach(item => {
      const key = Object.keys(item)[0]; //User
      if (className === key) {
        a = true;
      }
    })

    if (!a) {
      const strObj = JSON.parse(`{"${className}":{
        "defaults":[],
        "insert":[],
        "update":[],
        "insert_update":[]
      }}`)
      store.classFieldFill.push(strObj)// 如果没有就初始化
    }

    type A = "defaults" | "insert" | "update" | "insert_update"

    let types: A = (type.toLocaleLowerCase() as A);


    store.classFieldObj[className]?.forEach(item => {
      if (item[name]?.alias) {
        name = item[name].alias
      }
    })


    store.classFieldFill.forEach(item => {
      if (item[className]) {
        if (types.toString() === "default") {
          types = "defaults";
        }
        item[className][types]?.push(name)
      }
    })
  }
}

分为了四种模式,分别是default无作为,insert插入时填充,update更新时填充以及insert_update,插入或者更新时都填充
在这要说一个注意点

@fieldFill():要在@tableField()前使用,否则会导致字段名匹配不正确导致sql执行失败

这个是因为装饰器是洋葱模型,由外往内进入,由内往外执行,如果顺序不对的话,在指定了映射字段时,因为顺序问题,执行fieldFill()逻辑时获取不到映射字段导致更新失败 自动填充的使用方式:

const db = createDb({
  localhost: "localhost",
  root: "root",
  password: "123456",
  database: "tb_shudong",
})

初始化mysql实例

const queryWrapper = db.createWrapper(Demo); //实例化以便使用crud方法
db.initAutoWire(Demo);//返回值是三个函数,分别对应insert update insert_update
  • autoWireInsert({[propname:string]:Function}):插入时自动填充的逻辑
  • autoWireUpdate():更新时
  • autoWireUpAndIn():插入和更新时

传递参数的形式:{键:函数},函数必须有返回值,返回值作为列的值进行填充
键的形式,比如说类属性叫做addTime,那么键可以是addTime add_time或者@tableField指定

/**
 * 自动建表 ok 
 * insertInfo ok
 * deleteList ok 逻辑删除 ok
 * deleteById ok 逻辑删除 ok
 * getAll ok 逻辑删除 ok
 * getById ok 逻辑删除 ok
 * selectList ok 逻辑删除 ok
 * page ok
 * updateById ok 逻辑删除 ok
 * update ok 逻辑删除 ok
 * @fieldFill():要在@tableField()前使用,否则会导致字段名匹配不正确导致sql执行失败
 */

这是目前的功能,今天下午也已经通过测试
逻辑删除的话就是在方法内判断了一下罢了,简单贴一个栗子

async updateById(arr: T, id: string | number) {
    const update = this.objs.update;
    update.forEach((item: T) => {
      for (let i in item) {
        arr[i] = item[i]
      }
    })
    const update2 = this.objs.insert_update;
    update2.forEach((item: T) => {
      for (let i in item) {
        arr[i] = item[i]
      }
    })
    const { valueArr, updateStr } = this.getKeyAndValue(arr);
    let query = `update ?? set ${updateStr} where ${this.tableId}=?`;
    const arrss = [this.table, ...valueArr, id];
    if (this.options.logic_delete_field) {
      query += ` and ${this.options.logic_delete_field}!=?`;
      arrss.push(this.options.logic_delete_value)
    }
    const res = await this.sql(query, arrss);
    return res;
  }

主要就是前边的update以及update2的处理,但是这样的话自定义sql并不会应用自动填充,这也是后续要实现的功能,今天确实没有做很多,主要都是在改bug了,毕竟一次写完也没测试坑还是蛮多的heheheh

interface Options {
  localhost: string;
  root: string;
  password: string;
  database: string;
  tb_prefix?: string; //表前缀
  logic_delete_field?: string; //逻辑删除字段
  logic_delete_value?: string | number; //删除时的值
  logic_not_delete_value?: string | number; //没有删除时的值
}

贴一下初始化参数吧,主要是增加了后三个参数,然后改了一下两个类,初始化的类更专注于初始化,提供方法的类更注重方法,尽量让两个分工明确
具体代码就不贴了,毕竟改动蛮多了看着有点水哈哈哈哈
今天就说这么多,祝大家天天开心