Javascript 如何使用Bookshelf.js正确更新模型?
我确信我遗漏了一些东西,但我发现书架API对我来说总是令人困惑。以下是我正在尝试做的:Javascript 如何使用Bookshelf.js正确更新模型?,javascript,node.js,bookshelf.js,Javascript,Node.js,Bookshelf.js,我确信我遗漏了一些东西,但我发现书架API对我来说总是令人困惑。以下是我正在尝试做的: 我有一个名为Radio的模型,带有一个名为serial的应用程序分配字符串主键,在本例中,还有两个名为example1和example2的字段。我已在模型定义中使用idAttribute:“serial”指定了自定义ID 我正在尝试使用Bookshelf执行upsert(而不是直接使用Knex,在我的实际应用程序中,查询变得相当复杂) 我已使插入案例正常工作,但似乎无法使更新案例正常工作 为了简单起见,我现
- 我有一个名为
的模型,带有一个名为Radio
的应用程序分配字符串主键,在本例中,还有两个名为serial
和example1
的字段。我已在模型定义中使用example2
指定了自定义IDidAttribute:“serial”
- 我正在尝试使用Bookshelf执行upsert(而不是直接使用Knex,在我的实际应用程序中,查询变得相当复杂)
- 我已使插入案例正常工作,但似乎无法使更新案例正常工作
- 为了简单起见,我现在不关心事务或原子性。我很满意得到一个简单的选择→ 插入/更新以工作
- 在插入集
和example1
上example2
- 在更新集
时,保持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
构造函数(例如模型
mean…?),并且您可以在保存之前使用newx(a:1).save({a:2})
设置属性。所以我无法理解这一点。我必须将set
作为占位符传递,以便指定选项{}
- 有这个东西,但我不确定它的用途是什么,因为您已经可以将属性传递给
模型
构造函数(除非作者发现
vs.X.forge({a:1})
?)newx({a:1})
- 我发现我必须显式地指定要保存的方法,因为书架上有一个明显的怪癖:书架根据
选择方法,但是isNew()
在将id传递给模型构造函数时总是isNew()
,在应用程序分配id的情况下必须这样做。因此,对于应用程序分配的IDs,Bookshelf将始终执行“插入”,因为它始终认为模型“是新的”。因此,您必须强制该方法“更新”。。。这只会让我的书架更加混乱true
更重要的是,这些记录在哪里?诚恳地说,我假设它在某个地方被清楚地记录了下来,而我现在只是看不到森林中的树木,所以我实际上更希望在文档中遵循一些方向,而不仅仅是一个直接的答案,因为我确实需要弄清楚这一点。我花了很多时间在书架上而不是实际的开发上,以至于我几乎希望从一开始就坚持使用直接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();
}