我试图在模型中增加一个非自动递增的整数列,它完全独立于模型的自动递增ID。
为了简化我想说的话,考虑一张放书的桌子。在这个表中,我们有四个字段:
Book_id (auto incrementing ID)
book_title (a string)
book_contents (Also a string for the purposes of this example)
book_edition (an integer representing the edition of the book. Think College textbooks)
我们有一本书叫《哈利波特》,另一本叫《米老鼠》。我们的数据库目前看起来是这样的
id: 1
book_title: "Harry Potter"
book_contents: "Book Contents"
book_edition: 1
--------------------------
id: 2
book_title: "Mickey Mouse"
book_contents: "This is a book about Mickey"
book_edition: 1
现在让我们说,出于某种原因,“哈利波特”这本书必须有重大的改变,无论是因为“导演削减”或是与之相当的书,或是其他原因。这个条目将如下所示
id: 3
book_title: "Harry Potter"
book_contents: "Updated book contents"
book_edition: 2
我的问题是什么是最好的方式去抓住原来的图书版本在拉维尔5+?
我真的需要做一个Model::where({{query to get latest})或者我可以用另一种方式来处理这个问题吗?我看到有一个增量函数,但是没有很好地记录下来
作为第二个问题,如果我做了一个Model::上面提到过的地方,如果我把它包装在一个Laravel DB::事务中,我是否受到保护,免受两个人同时更新哈利波特书的可能的竞争条件的影响?
例子
function saveBook()
{
DB::transaction(function ($arr) {
$latest = Book::where('book_title', '=', 'Harry Potter')->orderBy("book_edition", "desc")->first();
$this->book_edition = $latest->book_edition + 1;
$this->save();
});
}
有可能在这里遇到种族问题吗?
提前谢谢!
最佳答案
从book_title
和book_edition
生成复合唯一索引应该可以从一开始就解决问题:
ALTER TABLE `books` ADD UNIQUE `unique_edition`(`book_title`, `book_edition`);
在这种情况下添加事务不会带来任何好处,因为您只执行一个写操作,虽然这取决于读操作的结果,但已通过唯一索引约束受到保护,不受任何竞争条件的影响。
要处理唯一异常,可以执行以下操作:
function saveBook()
{
...
$latestEdition = Book::where('book_title', 'Harry Potter')->max('book_edition');
$this->book_edition = $latestEdition + 1;
try {
$this->save();
} catch (Illuminate\Database\QueryException $e) {
// Your checking for 1062 because that's
// the MySQL error message for duplicate entry
if ($e->errorInfo[1] == 1062) {
// set your error message here
}
}
...
}
您还可以查看使用Pessimistic Locking,但这只是一种替代方法,因为如果您已经使用了唯一约束,那么锁定将是多余的。但在这种情况下,唯一的约束更有意义。
关于php - Laravel在没有竞争条件的情况下保存之前获取最新的非增量值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35660260/