0

在我的 java webappication 中,有一个操作可以更新订单对象并通过 ajax 调用(POST 请求)将其保存在数据库中。

方法saveOrder() 执行这个动作,如果多个用户执行相同的动作,这个方法应该有锁,以便用最新的数据执行写事务。

类文件代码如下

public class OrderLoader extends JSONProcessSimple {

@override
public JSONObject exec(JSONObject jsonsent) throws JSONException, ServletException {
  JSONObject result = this.saveOrder(array);
  return result;
}

public JSONObject saveOrder(JSONArray jsonarray) throws JSONException {
        JSONObject jsonResponse = new JSONObject();
        //Write operation on DB
        return jsonResponse;
    }
}

是否可以通过同步方法,请给我一个解决方案。

提前致谢!

4

4 回答 4

2

根据您的应用程序的架构(它是否在集群环境中的多个并行实例中运行?),没有简单的解决方案;如果它仅在一个 VM 中执行,synchronized可能是一种方法。另外,看看java.util.concurrent.lock包。

对于更复杂的分布式方法,您可以实现基于 DB 的锁。

于 2013-09-13T10:40:29.353 回答
2

更好的解决方案是检查您的数据库isolation和 SQL。也许您需要一个 SERIALZIABLE 连接或事务管理器。那是服务器端。

添加关键字很容易synchronized,但我认为不止于此。

http://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html

http://www.precisejava.com/javaperf/j2ee/JDBC.htm

于 2013-09-13T10:40:31.557 回答
1

单独同步不会完成这项工作,因为您会阻塞直到第一个请求被保存,然后您仍然需要检查其他订单是否更新。

正如其他人已经说过的那样,没有简单的解决方案,这取决于您的架构和环境。

您可能想尝试一些乐观的锁定方法,即每次更新都会检查一个版本列并在版本匹配时增加它。类似于... SET version = x + 1 WHERE version = x 然后您检查列是否已更新。

这不会保存最新的订单,但会防止丢失更新。但是,您可以调整该方法以仅在您有更新数据时更新数据库(可能基于某个日期,然后使用WHERE date > x)。

编辑

由于您使用的是 Hibernate,因此我会研究 Hibernate 的乐观锁定。这至少可以处理并发编辑,因为只有第一个会成功。如果非并发编辑导致 OptimisticLockExceptions,您可能会在某处遗漏(重新)读取。

对于并发编辑,我的意思是用户 A 读取对象,更改它,然后触发写入。在这之间,用户 B 也读取了对象并稍后触发了写入。写入不是并发的,但用户 B 没有看到用户 A 的更改,因此可能导致更新丢失。

在您的情况下,这取决于对订单执行的操作。在某些情况下,您可能会在持久化更改之前安全地重新读取订单(例如,添加职位时,删除它们时甚至可以这样做 - 如果职位不存在,您什么也不做),而在其他情况下,您可能想上报并发编辑(如两个用户同时编辑同一仓位的数量、订单表头等)

于 2013-09-13T10:47:16.093 回答
0

如果您的方法为不同的用户更新订单,那么您不需要进行任何同步,因为每个访问该方法的线程都有自己的副本,因此这不是问题。

但是如果所有用户都在处理相同的数据,您可以在 begintransaction 和 endtransaction 中使用 write to db。这应该使并发写入线程安全。

于 2013-09-13T10:45:20.507 回答