在数据库中管理产品计数 - java

如果这个问题看似天真,请原谅,但是我遇到了一种情况,我需要在电子商务商店的数据库中管理产品数量。

有一个带有整数变量productCount的Product类,它表示该站点的用户可见的数据库中可用产品的数量。现在,可以通过多个线程访问该类,或者可以说电子商务站点的多个用户。每个人都在将产品添加或删除到他的购物车中。

使用的ORM框架处于休眠状态

样例代码

@Entity
@Table
class Product{
   @Column
   private int productCount;

   public void addProductToCart(){
     // decrements the product count by 1 & updates the database
   }

   public void removeTheProductFromTheCart(){
    // increments the product count by 1 & updates the database
   }

从代码中可以明显看出,我需要对数据库中的产品数量进行并发检查,以防止更新丢失。

同样,如果有多个用户试图在数据库中仅添加单个剩余产品。产品应添加到哪个用户的购物车?

我对此做了一些研究

我发现的可能方法是

  • 为产品创建一个单例类。这样可以确保整个应用程序中只有一个产品实例可用。
  • 同步addProductToCartremoveTheProductFromTheCart方法。
    这将只允许一个线程一次更新产品计数并一次更新数据库。
  • 使用数据库并发控制应用一些db事务隔离级别,对productCount进行乐观/悲观锁定。我正在使用mysql,默认隔离级别是REPEATABLE_READ
  • 处理此问题的最佳方法是什么?

    参考方案

    对于您正在考虑的前两种可能性,只有当您仅限于部署应用程序的单个实例时,这些方法才起作用。您不能在多个应用程序实例之间管理单例,也不能在多个JVM之间进行同步。因此,如果您选择其中之一,则部署选项将受到限制,部署应用程序多个实例的唯一方法是将会话固定在特定实例上,这对负载均衡不利。因此,这些似乎都是不可取的。

    从数据库获取产品计数的方法的优点是,当您的应用程序在多个实例之间扩展时,它仍然有效,而不会破坏负载平衡。

    您可能会认为,这只是一台服务器上的一个实例,因此我可以解决这个问题。但是在您构建应用程序时,可能尚不清楚如何部署应用程序(我曾经遇到过这样的情况,直到我们在预生产环境中设置应用程序之前,我们都不知道计划是什么) ,或者日后可能有理由更改应用程序的部署方式;如果您的应用程序负载超出了预期,那么设置第二个盒子可能会有所帮助。

    对我而言,不明显的一件事是,产品数量正确无误至关重要。在不同的业务领域(机票,船运)中,超额预订是很常见的,而且保持100%准确的计数可能比值得多麻烦,特别是如果它是在流程的早期(例如向购物添加商品)购物车(与客户实际承诺购买的点相比)。在客户购买商品时,确保您通过数据库交易保留这些商品可能更有意义(或者不是,请再次进行超额预订)。

    在Web应用程序中,通常期望从购物车中的物品到实际购买的物品的转换率较低。请记住,计数的准确度水平适合您的业务领域。

    Java:线程池如何将线程映射到可运行对象 - java

    试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

    JAVA:字节码和二进制有什么区别? - java

    java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

    java:继承 - java

    有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

    Java:BigInteger,如何通过OutputStream编写它 - java

    我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…

    Java DefaultSslContextFactory密钥库动态更新 - java

    我有一个使用org.restlet.engine.ssl.DefaultSslContextFactory的现有应用程序和一个在服务器启动时加载的密钥库文件。我有另一个应用程序,该应用程序创建必须添加的证书服务器运行时动态地更新到密钥库文件。为此,我在代码中创建了证书和私钥,然后将其写入到目录。该目录由bash脚本监视,该脚本检查是否有新文件,如果出现,它将…