我有一个服务器功能,许多客户端都会同时调用它。服务器功能执行以下操作:
当两个或多个客户端同时运行该函数时会出错,多个x对象被添加到数据库中。
我只是通过使用同步方法创建一个单例管理器类来解决这个问题。
很好地工作,因为现在该功能一次只能由一个客户端调用。 (但是当有2台服务器时我确实遇到了问题,但事实并非如此)
但我想知道有更好的方法用jpa解决这个问题吗?
答案 0 :(得分:3)
是的,整个操作应该在事务中执行,例如由JTA或Spring的@Transactional
提供。如果事务被隔离在适当的级别(对于这种情况,我认为REPEATABLE_READ
),底层持久性系统将确保不会发生冲突写入,通过阻塞一个事务直到另一个事务完成(基本上是{ {1}}在Java中执行,或者在检测到冲突时停止并回滚第二个事务(然后可以重试)。
答案 1 :(得分:3)
我能想到的唯一万无一失的解决方案是创建数据库级约束。这是因为
synchronized
会影响应用程序性能,因为用户必须在其他用户执行操作时排队等候,我相信在任何情况下都不会接受这种情况。您需要为列值创建约束以进行简单数据验证,例如not null
或unique
等等。对于复杂情况,我所做的是在数据库表上创建一个检查值的触发器正在插入或更新的内容,如果它违反了条件,它将SIGNAL
SQLSTATE
甚至设置一条消息,提供失败原因,您可以在Java代码中处理这些异常,以便向用户发送相应的消息。为此,你需要对PL/SQL
知之甚少,如果你不了解它并不难以学习和实现它。看看这个问题here和一些类似的背景。
现在某些情况下,如果您使用的数据库不支持,例如,您无法直接创建数据库级别约束。几乎所有NoSQL
个数据库,如果数据库为MySQL
且表格的引擎为MyISAM
等,那么在这些情况下你所能做的就是使用某些write
commit
锁定通过多个应用程序实例之间的一些常见应用程序代我没有在这种情况下试图找到适当的解决办法,因为这种情况很少发生。
答案 2 :(得分:0)
这里有人回答了类似的问题(Double Checked Locking in Singleton),解决方法是双重检查锁定单例。我要做的一个小调整是我不会创建对象x,而是在数据库中搜索值为== param1(如果可行)的行。