【问题标题】:JPA insert transaction concurrencyJPA 插入事务并发
【发布时间】:2012-09-13 05:54:42
【问题描述】:

我有更多的理论问题: 数据何时插入数据库?是在持久化之后还是在调用提交之后?因为我对唯一键(手动生成)有疑问 - 它们会重复。我认为这是由于多个用户同时将数据插入到同一个表中。

更新 1:

我在我的应用程序中生成密钥。键示例:'123456789123'、'123456789124'、'123456789125'...

键字段是varchar类型,因为有很多旧键(我无法删除或更改它们),例如'VP123456','VP15S3456'。另一个问题是,在将它们插入一个数据库之后,这些键必须插入另一个数据库。而且我不知道什么是 DB 序列和 Atomic 对象..

更新 2:

这些密钥用于财务文档,而不是数据库密钥。所以它们必须是唯一的,但它们在编程的任何地方都不能用作对象键。

【问题讨论】:

  • “...这些密钥必须插入另一个数据库”是什么意思。它们在那里也被用作钥匙吗?这些“密钥”真的有必要成为您的技术数据库密钥吗?
  • 我更新(更新 2)我的问题。

标签: java jpa concurrency transactions


【解决方案1】:

我建议您创建一个负责生成密钥的 Singleton。确保只有在使用数据库中的最新值初始化单例后才能获取新 id。

为了防止您不完整地插入两个数据库,我建议您尝试使用XA transactions。这将允许您进行全有或全无的插入和更新。因此,如果任何数据库上的任何操作失败,所有内容都将回滚。当然 XA 交易也有缺点。它们非常慢,并且并非所有数据库和数据库驱动程序都支持它。

【讨论】:

  • 此解决方案是否可以防止多用户?我的意思是,如果两个或多个用户在使用此应用的不同计算机上同时向同一个表中插入数据?
  • 嗯,这当然取决于您所说的“应用程序”是什么意思。如果您的程序在服务器上运行并且有多个客户端连接到它,那么是的,它将(如果操作正确)防止并发问题。如果您在每个用户的 PC 上运行多个程序并且只连接到相同的数据库,那么它会给您带来与开始时相同的问题。
  • 谢谢。我现在看到避免重复的唯一解决方案是在新行插入时生成该字段(我的应用程序是没有服务器的独立桌面应用程序)。我不能这样做,所以我会想一些解决方法。
【解决方案2】:

如何生成这些密钥?您是否尝试过在 DB 或原子对象中使用序列?

我问是因为同时填充数据库是正常的。

编辑1:

您可以编写一个基于原子计数器返回新密钥的方法,这样您就会知道,每当您请求新密钥时,您都会收到一个唯一密钥。这种策略可能并且将会导致一些键被丢弃,但这是一个很小的代价,除非它要求数据库中的键是连续的。

private AtomicLong counter; //initialized somewhere else.

public String getKey(){
  return "VP" + counter.incrementAndGet();
}

这里有一些关于OracleMySql 等数据库序列的帮助

【讨论】:

  • 在应用程序中生成密钥通常是个坏主意。有很多事情你需要照顾。使用原子数据类型仅仅是开始。您必须绝对确定在任何给定时间只有一个 id 生成类的实例正在运行。此外,您必须注意正确的初始化等。如果人为可能,让数据库来处理这个问题。要么使用序列(最好的方法),要么,如果你需要做一些奇怪的事情来生成 id,使用存储过程(它可能也会在内部使用序列)。
  • 问题是我无法更改数据库的许多方面,解释原因太复杂了——我只是不允许这样做。这些键的生成背后有一些逻辑 - 新行是一个项目,女巫属于一个组。该组有自己的密钥(同样不是数据库密钥)女巫是项目密钥的开始......
猜你喜欢
  • 2011-07-05
  • 2013-04-09
  • 1970-01-01
  • 1970-01-01
  • 2021-10-03
  • 2011-05-24
  • 2013-09-10
  • 2016-07-21
  • 1970-01-01
相关资源
最近更新 更多