考虑Spring MVC
java web-application,它提供了一些REST API
。
我们说它有很多方法,其中一个方法是DELETE /api/foo/{id}
,显然会从给定foo
的数据库中删除id
实体。
问题是由于数据库中的大数据,此操作不是立即的,因此如果客户端尝试在同一实体上同时执行多次删除操作,请说
DELETE /api/foo/123
x次(当然在客户端软件中出错),
它会在数据库中造成一些令人不快的副作用(你知道,如果你尝试在几个交易中删除相同的实体,那通常不太好)。
我的问题是:Spring MVC
中防止此类情况的最佳做法是什么?
我当然可以在每个此类更新方法(Foo
)中引入PUT/DELETE
id的同步。我需要为所有实体和所有PUT/DELETE
API方法执行此操作,但我真的不想这样做。我想它应该是一些优雅而好的解决方案,如何在拦截器/ servlet级别上执行这种类型的同步,即不在控制器级别的服务上。
我还可以创建特定的拦截器并在那里等待重复的请求(具有相同URL和参数的请求)。但同样,它听起来并不是一个优雅的解决方案(直到我确保无法以更美的方式在Spring MVC
中进行配置)。
答案 0 :(得分:1)
这是一个并发问题,应该通过使用适当的事务和锁定级别来处理。不幸的是,这里没有任何单一尺寸可供选择,根据您的实际需求,您可能必须实施乐观或悲观锁定,以及可能的事务级别之一(从无交易到可序列化事务)。
一般来说,在网络级别处理这些问题是一个坏主意,因为你会在请求中做什么等问题想要删除另一个同时显示的数据?在SpringMVC中,常见的方法是在服务层中使用事务方法。另外,您应该在持久层中声明一个乐观或悲观的锁定系统。
乐观层通常会提供更高的吞吐量,代价是以异常结束的某些事务。在这种情况下,目前的最佳做法是向用户报告问题,要求他/她再次发送他/她的请求。