【发布时间】:2017-06-05 16:34:54
【问题描述】:
假设我有一个带有这样方法的 java 类(只是一个例子)
@Transactional
public synchronized void onRequest(Request request) {
if (request.shouldAddBook()) {
if (database.getByName(request.getBook().getName()) == null) {
database.add(request.getBook());
} else {
throw new Exception("Cannot add book - book already exist");
}
} else if (request.shouldRemoveBook()) {
if (database.getByName(request.getBook().getName()) != null) {
removeBook();
} else {
throw new Exception("Cannot remove book - book doesn't exist");
}
}
}
假设这本书被删除,然后重新添加了一个新作者或其他微小的变化,所以这个方法可能会从另一个系统快速调用两次,首先是删除这本书,然后再添加相同的书(使用一些新的细节)。
为了处理这个问题,我们可能会尝试(像我一样)添加上面的@Transactional 代码,然后在@Transactional 不起作用时也“同步”。但奇怪的是,它在第二次调用时失败了
“无法添加图书 - 图书已存在”。
我花了很多时间试图弄清楚这一点,所以我想我会分享答案。
【问题讨论】:
-
如果你想改变细节,你更新它。您不会删除并添加它。这是可怕的设计。如果你做事正确,你就不需要
synchronized。 -
这个问题没有真正找到,因为我想更新一本书的细节。就像你说的那样,那将是糟糕的设计。这只是一个例子。然而,这种模式可能会发生还有其他原因,其他人可能会像我一样遇到这种奇怪的情况,所以我想向其他人展示为什么它不起作用,这样他们就不必花这么长时间来试图理解和我一样。
-
对我来说同样的问题。例如创建对象时检查重复名称。我用
onRequest的同步调用方法解决了这个问题。
标签: java spring synchronized transactional