Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用Bookshelf.js正确更新模型?_Javascript_Node.js_Bookshelf.js - Fatal编程技术网

Javascript 如何使用Bookshelf.js正确更新模型?

Javascript 如何使用Bookshelf.js正确更新模型?,javascript,node.js,bookshelf.js,Javascript,Node.js,Bookshelf.js,我确信我遗漏了一些东西,但我发现书架API对我来说总是令人困惑。以下是我正在尝试做的: 我有一个名为Radio的模型,带有一个名为serial的应用程序分配字符串主键,在本例中,还有两个名为example1和example2的字段。我已在模型定义中使用idAttribute:“serial”指定了自定义ID 我正在尝试使用Bookshelf执行upsert(而不是直接使用Knex,在我的实际应用程序中,查询变得相当复杂) 我已使插入案例正常工作,但似乎无法使更新案例正常工作 为了简单起见,我现

我确信我遗漏了一些东西,但我发现书架API对我来说总是令人困惑。以下是我正在尝试做的:

  • 我有一个名为
    Radio
    的模型,带有一个名为
    serial
    的应用程序分配字符串主键,在本例中,还有两个名为
    example1
    example2
    的字段。我已在模型定义中使用
    idAttribute:“serial”
    指定了自定义ID
  • 我正在尝试使用Bookshelf执行upsert(而不是直接使用Knex,在我的实际应用程序中,查询变得相当复杂)
  • 我已使插入案例正常工作,但似乎无法使更新案例正常工作
  • 为了简单起见,我现在不关心事务或原子性。我很满意得到一个简单的选择→ 插入/更新以工作
特别是在这个例子中:

  • 在插入集
    example1
    example2
  • 在更新集
    example1
    时,保持
    example2
    不变
所以我在书架模型中有类似的东西,作为一个类(即“static”)方法(“info”有字段“serial”、“example1”和“example2”):

示例调用:

Radio.insertOrUpdate({
    serial: ...,
    example1: ...,
    example2: ...
})
我在这里遇到的问题是,“插入”案例起作用时,“更新”案例失败,原因是:

ERROR { Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where `serial` = '123223'' at line 1
这在启用Knex调试时很明显,其中生成的查询缺少
set
子句:

update `radios` set  where `serial` = ?
现在,我专注于和的书架文档,我想知道我是否走错了方向

我知道我使用的API是错误的,但我无法理解。为了让它进入半工作状态,我注意到/不得不做一些奇怪的事情:

  • 我不明白
    save
    的第一个参数。如果save是
    Model
    的一种静态方法,对我来说是有意义的,但事实并非如此。这是一个实例方法,您已经可以将属性传递给
    模型
    构造函数(例如
    newx(a:1).save({a:2})
    mean…?),并且您可以在保存之前使用
    set
    设置属性。所以我无法理解这一点。我必须将
    {}
    作为占位符传递,以便指定选项

  • 有这个东西,但我不确定它的用途是什么,因为您已经可以将属性传递给
    模型
    构造函数(除非作者发现
    X.forge({a:1})
    vs.
    newx({a:1})
    ?)

  • 我发现我必须显式地指定要保存的方法,因为书架上有一个明显的怪癖:书架根据
    isNew()
    选择方法,但是
    isNew()
    在将id传递给模型构造函数时总是
    true
    ,在应用程序分配id的情况下必须这样做。因此,对于应用程序分配的IDs,Bookshelf将始终执行“插入”,因为它始终认为模型“是新的”。因此,您必须强制该方法“更新”。。。这只会让我的书架更加混乱

不管怎样,我该怎么做?如何使此插入和更新工作


更重要的是,这些记录在哪里?诚恳地说,我假设它在某个地方被清楚地记录了下来,而我现在只是看不到森林中的树木,所以我实际上更希望在文档中遵循一些方向,而不仅仅是一个直接的答案,因为我确实需要弄清楚这一点。我花了很多时间在书架上而不是实际的开发上,以至于我几乎希望从一开始就坚持使用直接SQL查询。

经过几次反复的猜测,我似乎已经让它工作了,但我不知道这是否正确,也不知道如何在没有猜测的情况下确定它,我绝对不支持它的正确性

基本上,我通过将“更新”案例修改为:

  • 将属性作为第一个参数传递给
    save
    ,而不是使用
    set
    设置属性
最终解决以下问题:

insertOrUpdate: function (info) {
    return new Radio({'serial':info.serial}).fetch().then(function (model) {
        if (model) {
            // pass params to save instead of set()
            var params = { 'example1' : info.example1 }
            return model.save(params, {
                method: 'update',
                patch: true
            })
        } else {
            return new Radio({
                serial: info.serial,
                example1: info.example1,
                example2: info.example2
            }).save({}, {
                method: 'insert'
            })
        }
    }).then(function (model) {
        console.log("SUCCESS");
    }).catch(function (err) {
        console.log("ERROR", err);
    });
}
我仍然不确定
forge
如何/是否适合这里,或者在“insert”的情况下,第一个参数
save
应该如何处理


更重要的是,我现在还不能完全确定
set
的用途。ORM框架的一个主要好处是使这类内容透明(即“保存”正确工作,同时允许您使用模型而不必考虑它,也不必知道在“保存”时发生了什么变化)--我应该能够拥有未知的任意代码
提前设置
内容,然后能够在不知道更改了什么的情况下保存它,但看起来我不能),所以我不确定我从这里的书架上实际获得了什么。一定有更好的方法。

这是一个有趣的方法,我花了一些时间去了解发生了什么

正如您所发现的,关于
补丁
选项的
save()
方法声明

仅保存要保存的参数中提供的属性

所以您只需要将代码更改为

if (model) {
    model.set('example1', info.example1);
    return model.save();
}
并且将保存
设置
属性

但是但是但是但是但是

所有属性都将进入
update
语句,甚至
id

这是ORMs的一种常见行为,其基本原理是,如果我们从一个事务中获取数据并从另一个事务中保存数据(糟糕,糟糕的做法!),那么数据可能已被其他客户机更改。因此,仅保存部分属性可能会导致状态不一致

但是
补丁
属性的存在违反了这个概念。因此,书架可以通过以下方式进行改进:

  • 只需弃用
    补丁
    选项即可。(我更喜欢那样)
  • <
    if (model) {
        model.set('example1', info.example1);
        return model.save();
    }