java - 如何防止在两个事务中产生重复值

标签 java mysql spring hibernate race-condition

我有一个 Spring Boot 应用程序,它通过 REST API 获取请求。

收到这样的请求后,我为我的对象生成了一个 offerID。这不是数据库的主键,它只是我们与客户交流的人类可读数字,而不是普通的数据库 ID。

对于我们在 2016 年 5 月 18 日收到的第一个请求,此优惠 ID 类似于“16051801”。

这在数据库中存储为字符串以选择当前“最大值”,类似 SELECT count(r) FROM Request as r WHERE r.offerId LIKE ?1% 我只是输入当前日期“160518”并获取存储在那里的请求数,然后将计数 + 1 作为下一个值。

您可能已经猜到,这会带来一些问题。

一方面,这工作正常,因为我们现在在这个网站上没有那么多流量。

但是,如果我们有两个请求几乎同时进入,我会得到类似“竞争条件”的东西,并且我创建了相同的 offerId 两次,这不是很酷。

我已经为此列添加了一个唯一约束,它可以防止创建具有相同值的多个条目,但在那种情况下,两个请求之一会失败。

我已经尝试过类似的东西:

try {
     super.create(customerRequest);
} catch (DataIntegrityViolationException ex) {
     if (ex.getCause() instanceof ConstraintViolationException) {
         ConstraintViolationException constraintViolationException = (ConstraintViolationException) ex.getCause();
         if (constraintViolationException.getCause().getMessage().contains("'UC_CUSTOMERREQUESTOFFERNUMBER_COL'")){
             customerRequest.setOfferNumber(generateOfferNumber(customerRequest));
                 super.create(customerRequest);
        }
    }
}

但在那种情况下,我总是得到类似Do not flush the session if an Exception occurs

基本上在那种情况下我能够处理和解决问题,但 Spring/Hibernate 阻止我这样做。

所以真正的问题是,以一种不老套的方式处理这种“问题”的最佳实践是什么(我也尝试过使用 Thread.sleep() 的东西,感觉不太好......)并且还具有可扩展性(将来也应该适用于应用程序的多个实例)。

作为数据库,我们使用 MySQL,据我所知,我们无法将此“ID 生成”移动到数据库中。

最佳答案

MySQL 本身就没有序列的概念。 最接近的是 AUTO_INCREMENT。

对于 MyISAM 表,您需要一种简单的方法。只需将订单的日期保存在表中,并根据日期自动递增。

MYSQL手册是这样说的:

“对于 MyISAM 表,您可以在多列索引的辅助列上指定 AUTO_INCREMENT。在这种情况下,AUTO_INCREMENT 列的生成值计算为 MAX(auto_increment_column) + 1 WHERE prefix=given-prefix。当您想将数据放入有序组时,这很有用”

查看此链接以获取更多信息。 http://dev.mysql.com/doc/refman/5.7/en/example-auto-increment.html

关于java - 如何防止在两个事务中产生重复值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37291446/

相关文章:

java - 通过 MainActivity.java 设置我的 textView 的问题

php - 在 PHP 中的动态页面上搜索

java.util.Date 来自<输入类型 ="datetime-local"/>

java - 如何模拟 RestTemplate

Java Selenium FirefoxDriver 忽略给定的代理设置

Java 泛型返回类型

mysql - 计算表中多级标准的权重

java - XMPP - Spring 集成 : Does the spring application run an embedded XMPP server

java - 如何将应用程序审计记录到 Wildfly 8 上的单独文件

mysql - 使用表中的连接和更新计算列值