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