gpt4 book ai didi

java - Spring JPA 与 Hibernate 财务序列生成

转载 作者:搜寻专家 更新时间:2023-11-01 01:51:03 25 4
gpt4 key购买 nike

在我的应用程序中,我正在建模发票。在我的国家(意大利),每张发票都必须有一个唯一的没有漏洞的序列号,每年都必须从 1 重新开始。

我仔细考虑了实现它的最佳方法,但我还没有找到一个很好的指南。现在我有一个 JpaRepository我在哪里有我的自定义同步 save()我获取最后使用的 id 的方法:

SELECT MAX(numero) FROM Invoice WHERE YEAR(date) = :year

这种方法的问题是不是很安全,因为开发人员应该知道只应使用该特定服务进行保存。

相反,我更想要一种对开发人员隐藏的方法。
我想用 @Prepersist @EntityListeners 中的方法.这听起来不错,但是在这个类中使用实体管理器并不是那么简单......所以也许不是最佳位置......

最后我想到了 Hibernate Interceptor ....

请给我一些提示。这个问题似乎是一个非常普遍的问题;所以也许还有一个很好的做法可以遵循。

谢谢

最佳答案

这个问题可以分解为以下需求:

  • 顺序唯一 :按顺序生成数字,从给定值(例如 1000001 )开始,然后始终以固定值递增(例如, 1 )。
  • 无间隙 : 数字之间不能有任何差距。所以,如果生成的第一个数字是 1000001 ,增量为 1到目前为止已经生成了200个号码,最新的号码应该是1000201 .
  • 并发 :多个进程必须能够同时生成数字。
  • 创建时生成 :数字必须在创建记录时生成。
  • 无排他锁 :生成数字不需要排他锁。

  • 任何解决方案都只能符合这 5 个要求中的 4 个。例如,如果要保证 1-4,则每个进程都需要获取锁,以便其他进程无法生成和使用它已生成的相同数字。因此,将 1-4 作为要求将意味着必须放弃 5。同样,如果要保证1、2、4、5,则需要保证一次只有一个进程(线程)生成一个数,因为在没有加锁的并发环境下无法保证唯一性。继续这个逻辑,你就会明白为什么不可能同时保证所有这些要求。

    现在,解决方案取决于您愿意牺牲 1-5 中的哪一个。如果您愿意牺牲 #4 而不是 #5,您可以在空闲时间运行批处理以生成数字。但是,如果您将此列表放在业务用户(或财务人员)面前,他们会要求您遵守 1-4,因为 #5 是一个纯粹的技术问题(对他们而言),因此他们不想成为打扰了。如果是这种情况,可能的策略是:
  • 预先执行生成发票所需的所有可能计算,将发票编号生成步骤作为最后一步。这将确保任何可能发生的异常都在生成数字之前发生,并确保锁定的时间非常短,从而不会过多地影响应用程序的并发性或性能。
  • 保留一个单独的表(例如, DOCUMENT_SEQUENCE )以跟踪最后生成的数字。
  • 就在保存发票之前,对序列表进行排他行级锁(例如,隔离级别 SERIALIZABLE ),找到要使用的所需序列值并立即保存发票。这不应该花费太多时间,因为读取一行、增加其值和保存记录应该是一个足够短的操作。如果可能,使这个短事务成为主事务的嵌套事务。
  • 保持足够的数据库超时,以便并发线程等待 SERIALIZABLE锁不要超时太快。
  • 将整个操作保持在重试循环中,在完全放弃之前至少重试 10 次。这将确保如果锁队列建立得太快,在完全放弃之前仍会尝试几次操作。许多商业包的重试次数高达 40、60 或 100。

  • 除此之外,如果可能并且您的数据库设计准则允许,请在发票编号列上设置唯一约束,以便不惜任何代价存储重复值。

    Spring 为您提供了实现这一点的所有工具。
  • 交易 : 通过 @Transactional 注解。
  • 序列化 : 通过isolation @Transactional 的属性注解。
  • 数据库访问 : 通过 Spring JDBC , Spring ORMSpring Data JPA .
  • 重试 : 通过 Spring Retry .

  • 我有一个 sample app这演示了将所有这些部分一起使用。

    关于java - Spring JPA 与 Hibernate 财务序列生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31751744/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com