• 首页
  • javascript
  • sequelize 5.0中文文档 对象实例操作与数据持久化 (五) - node.js语言最好用的orm

sequelize 5.0中文文档 对象实例操作与数据持久化 (五) - node.js语言最好用的orm

image.png


文章目录



前言

在面向对象语言中,我们很容易理解对象及对象的实例,
但是sequelize ORM框架中我们通常会说成模型和实例.

模型可以理解为对一个表结构的抽象定义,好比工厂的一条流水线,
实例可以理解为表结构中一个具体的数据结构,好比流水线生产出来的一个商品.

在sequelize 类中有一些api是针对实例操作 (可以理解成内存中的改变)
实例持久化以后,数据才写入我们物理存储单元中 (比如具体的数据库)


新建实例并持久化


定义模型

const Task = sequelize.define('task', {
 title: Sequelize.STRING,
 rating: { type: Sequelize.STRING, defaultValue: 3 }
})

构建实例

构建非持久化实例

const task = Task.build({title: 'very important task'});
task.title  // ==> 'very important task'
task.rating // ==> 3,没有声明的值将设置为默认值

save持久化

为了持久化存储在数据库中,使用save方法.

task.save().catch(error => {
 // mhhh, wth!
})

链式写法

Task
 .build({ title: 'test' })
 .save()
 .then(anotherTask => {
   // 持久化成功
 })
 .catch(error => {
   // 捕捉错误
 })

build 构建对象
save 持久化对象


create持久化

我们日常持久化实例都用create,
调用此api,相当于走了2步:

  • 定义实例
  • 实例持久化
Task.create({ title: 'new title' }).then(task => {
 //构建了新实例,同时持久化到数据库
})

create持久化只会持久化模型中定义的属性,非定义属性自动抛弃
例如:

Task.create({ title: 'new title',desc:'xxxxxxxx' }).then(task => {
 //新实例持久化到数据库中的属性只有 title
})

未定义的属性 desc,并没有持久化成功.


更新实例并持久化

当我们需要对实例更改时,
如何将更改后的实例持久化.


save更新实例

task.title = 'update title'
task.save().then(() => {})

update更新实例

task.update({
 title: 'a very different title now'
}).then(() => {})

save 等价于 update,
未被定义的属性都将不能持久化.


destroy移除实例

Task.create({ title: 'destroy task' }).then(task => {
  //task就是该对象的引用
  return task.destroy();//然后就能够通过引用调用destroy方法删除它
}).then(() => {
 // 捕捉错误
})

也可以直接用实例的 destroy 方法,将对应的实例移除

Task.destroy({title:'destroy task'}).then(()=>{
    //实例移除成功
}); 

一次执行多个实例操作

除了更新单个实例,你也可以一次create, update, and delete多个实例.
当你执行的是多个模型,回调将不会返回DAO实例.
BulkCreate将返回模型实例/DAOs数组,不像create,没有自动增长属性的结果值.
update和destroy将返回被影响的行的数量.


Model.bulkCreate

批量创建

User.bulkCreate([
  { username: 'barfooz', isAdmin: true },
  { username: 'foo', isAdmin: true },
  { username: 'bar', isAdmin: false }
]).then(() => { // Notice: There are no arguments here, as of right now you'll have to...
  return User.findAll();
}).then(users => {
  console.log(users) // ... in order to get the array of user objects
})

bulkCreate通过添加validate: true属性,添加实例时将会去验证

const Tasks = sequelize.define('task', {
  name: {
    type: Sequelize.STRING,
    validate: {
      notNull: { args: true, msg: 'name 不能为null' }
    }
  },
  code: {
    type: Sequelize.STRING,
    validate: {
      len: [3, 10]
    }
  }
})

Tasks.bulkCreate([
  {name: 'foo', code: '123'},
  {code: '1234'},//失败,因为name不能为null
  {name: 'bar', code: '1'}//失败,code长度小于3
], { validate: true }).catch(errors => {
  /* console.log(errors) would look like:
  [
    { record:
    ...
    name: 'SequelizeBulkRecordError',
    message: 'Validation error',
    errors:
      { name: 'SequelizeValidationError',
        message: 'Validation error',
        errors: [Object] } },
    { record:
      ...
      name: 'SequelizeBulkRecordError',
      message: 'Validation error',
      errors:
        { name: 'SequelizeValidationError',
        message: 'Validation error',
        errors: [Object] } }
  ]
  */
})

Model. update

批量更新

Task.bulkCreate([
  {subject: 'programming', status: 'executing'},
  {subject: 'reading', status: 'executing'},
  {subject: 'programming', status: 'finished'}
]).then(() => {
  return Task.update(
    { status: 'inactive' }, /* set attributes' value */
    { where: { subject: 'programming' }} /* where criteria */
  );
}).spread((affectedCount, affectedRows) => {
  // 批量更新2条数据后,返回结果 spread 来接收返回值,自动拆分成2部分(见下方spread的说明)

  // affectedCount will be 2
  return Task.findAll();
}).then(tasks => {
  console.log(tasks) // the 'programming' tasks will both have a status of 'inactive'
})

注意:
上面 update 方法后使用 spread 方法来接收更新后的数据参数,
为什么不是 then ?


spread介绍

spread 的功能类似then,但是它有一个优点,可以把回调得到的数据拆分成2部分,
什么时候拆分
比如上面的 update 方法,
当你使用 postgresql数据库时,
当你设置update方法的 options.returning=true时,
执行成功后返回的结果集包含2部分

  • 影响的行数
  • 影响的数据
    当返回结果如上包含2部分时,sequelize 提供的 spread 方法可以拆分这2部分,
    常用的方法还有 findOrCreate
User
  .findOrCreate({where: {username: 'sdepold'}, defaults: {job: 'Technical Lead JavaScript'}})
  .spread((user, created) => {
    console.log(user.get({
      plain: true
    }))
    console.log(created)

    /*
    findOrCreate 返回一个包含已找到或创建的对象的数组,找到或创建的对象和一个布尔值,如果创建一个新对象将为true,否则为false,像这样:

    [ {
        username: 'sdepold',
        job: 'Technical Lead JavaScript',
        id: 1,
        createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET),
        updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET)
      },
      true ]

在上面的例子中,".spread" 将数组分成2部分,并将它们作为参数传递给回调函数,在这种情况下将它们视为 "user" 和 "created" 。(所以“user”将是返回数组的索引0的对象,并且 "created" 将等于 "true"。)
    */
  })

Model. destroy

批量删除

Task.bulkCreate([
  {subject: 'programming', status: 'executing'},
  {subject: 'reading', status: 'executing'},
  {subject: 'programming', status: 'finished'}
]).then(() => {
  return Task.destroy({
    where: {
      subject: 'programming'
    },
    truncate: true /* this will ignore where and truncate the table instead */
  });
}).then(affectedRows => {
  // 影响的行数 2
  return Task.findAll();
}).then(tasks => {
  console.log(tasks) // no programming, just reading :(
})

批量创建后然后批量删除.


Reloading重载实例

如果你想要同步得到你的实例,你可以使用方法reload重载.
他将从数据库获取当前的数据并覆写之前调用过方法的模型的属性(不改变数据库中原来属性值)

Person.findOne({ where: { name: 'john' } }).then(person => {
  person.name = 'jane'
  console.log(person.name) // 'jane'

  person.reload().then(() => {
    console.log(person.name) // 'john' 重载后 name 已经变成 john ,但是数据库中此记录的 name值依然是 jane
  })
})

递增和递减整数值

为了递增/递减实例的值而不会遇到并发问题,Sequelize提供了 increment 和 decrement 实例方法.

const jane = await User.create({ name: "Jane", age: 100 });
const incrementResult = await user.increment('age', { by: 2 });
// 注意: 如只增加 1, 你可以省略 'by' 参数, 只需执行 `user.increment('age')`

// 在 PostgreSQL 中, 除非设置了 `{returning:false}` 参数(不然它将是 undefined),
// 否则 `incrementResult` 将是更新后的 user.

// 在其它数据库方言中, `incrementResult` 将会是 undefined. 如果你需要更新的实例, 你需要调用 `user.reload()`.

你也可以一次递增多个字段

const jane = await User.create({ name: "Jane", age: 100, cash: 5000 });
await jane.increment({
  'age': 2,
  'cash': 100
});

// 如果值增加相同的数量,则也可以使用以下其他语法:
await jane.increment(['age', 'cash'], { by: 2 });

出自:sequelize 5.0中文文档 对象实例操作与数据持久化 (五) - node.js语言最好用的orm

回到顶部