2017-02-03 78 views
2

我目前正在研究从两个不同数据库读取和写入的RESTful Web服务。我遇到的问题是处理我的服务被调用的情况,然后在第一次完成写之前接收到第二个调用。该服务读取数据库中的日期字段以确定是否需要INSERT或UPDATE,然后在所选操作中写入该字段。如果第二次调用是在第一次调用完成之前完成的,那么日期字段将不会被写入,所以我最终得到两个INSERTS而不是INSERT和UPDATE。注入类方法的读/写锁定

我尝试使用java中可用的并发API以及groovy,但到目前为止我还没有得到它的工作。每次调用RESTful服务时,都会查找模型类的新副本。然后模型类通过依赖注入获取groovy对象的新实例。因此,我不能在任何地方放置Lock的实例,因为每次REST风格的服务调用都将在模型的新实例和groovy上进行。

任何人都可以提出一个更好的方法来做到这一点?任何帮助,将不胜感激。

更新

下面是一些服务伪代码

  1. 查找模型通过ID从数据库的表中的数据1.
  2. 查找最新的表B中的条目数据库2的id与存储在模型中的密钥(dw_id)匹配。
  3. 将结果的“开始日期”列与当前日期时间进行比较。

如果所述的起始日期==当前天然后的 '日':

4a上。使用从模型获得的数据 对数据库2的表B执行UPDATE查询。

否则

5A。在数据库2的表B上执行UPDATE查询,将昨天的日期替换为end_date列的 值,其中id == dw_id。 5b)。

5b。使用 模型中的数据对数据库2的表B执行INSERT,将start_date设置为今天的日期,将end_date设置为 不变的未来日期。

5c。在数据库1的表A上执行UPDATE,将模型的 的dw_id替换为由5b中的 INSERT创建的条目的自动生成的ID。

更新2

我最终实现一个类似于jan-willem-gmelig-meyling提出的解决方案的东西。我在这里找到了一个很好的例子:https://stackoverflow.com/a/27806218/32453,我能够适应我的需求。

+1

通常,锁定是数据库应该处理的事情,而且非常擅长。您应该尝试使用SQL进行操作,即case语句,在该语句中检查select的值以确定查询是插入还是更新。您正在使用的数据库将为您处理并发情况。 –

+0

如何把一个存储过程称为做所有的东西。然后处理存储过程中的锁定。 – JFPicard

+0

您能否提供一个使用case语句修改SQL查询类型的示例? – pbuchheit

回答

1

在Java中,您可以通过同步锁对象来实现此目的。但是,只有在开始数据库事务之前获得此锁定才有效。否则,这两个并行线程将同时启动一个数据库事务并生活在独立的数据库版本中。所以你大概得:

private final static Object lock = new Object(); 

public void myResource() { 
    synchronized (lock) { 
     // begin tx, do work, end tx. 
     // Other callee won't get here before first callee is finished 
    } 
} 

然而,这确实打破了所有服务器无国籍公约。实际上在事务中锁定数据库表要好得多。这可以防止另一个连接同时读取和写入同一个表。您可以调查哪些锁定机制支持您的数据库(或ORM库,如果使用的话)。诸如JTA之类的技术可以用来共享服务器,服务或多个数据库之间的数据库事务。

+0

当你说这打破了无状态服务器约定时,你能详细说明你的意思吗?如果我使用此解决方案,是否有潜在的副作用或需要注意的问题? – pbuchheit

+0

是的,因为您在静态锁定对象上进行同步,所以该锁定仅在同一个JVM中存在。因此,如果您在运行两个单独的JVM的两台服务器之间启动负载平衡,则此机制将不再起作用。然后你需要开发一些东西来锁定/同步多个节点。 –

+0

好的,很高兴知道。在这一点上,我们的应用程序不必处理。如果未来情况发生变化,您是否知道有哪些优秀的资源可以演示如何在数据库级别正确实现锁定? – pbuchheit