我有以下问题我必须保存表中某些元素的顺序。这是通过订单号完成的。所以第一个元素有订购1,第十个订单有10个等等。我也保存了品牌价值,这意味着订单只在一个品牌的所有行中。 我的配置是Spring 3.1,带有Hibernate 4.1.6和Spring Data,我也使用JPA接口,底层是一个Mysql数据库。
我现在有一个save方法,它通过namedquery获取最大值。然后将值递增1。现在使用对象设置器设置值。然后保存它。
if(tag.getOrdering()==0) {
int newOrderingNumber = tagRepository.getMaximumOrderingNumber();
newOrderingNumber++;
if(LOGGER.isDebugEnabled()) {
LOGGER.debug("Next Ordering Number for Tag is " + newOrderingNumber);
}
tag.setOrdering(newOrderingNumber);
}
这里我遇到一个问题,如果两个线程同时执行此操作会发生什么。 他们都会保存相同的价值。但是必须增加两次。 我的问题是如何防止这种情况发生。 首先,我尝试使用spring事务的隔离级别做一些事情,但是JPA会知道事务级别以及我如何在这里扩展jpadialect的方式(http://amitstechblog.wordpress.com/2011/05/31/supporting-custom-isolation-levels-with-jpa/) 但那没有用,我的Connection总是只读readOnly = false标志没有正确设置,我没有发现什么是错的。我认为这不会解决我的问题。
然后我尝试使用@Version属性,但这不起作用,因为我不在一个对象实例上工作。这两个线程正在处理两个不同的行,因此版本控制无法解决问题。
所以现在我看到了四种不同的方法。
首先:我可以在我的代码中使用同步锁定对象让一个线程等待另一个线程释放对象的锁定
第二:我可以获得一个完整的表锁,我不知道如何处理hibernate,它似乎也超大了阻止整个表。
第三:当我不想在其中排序可能相同的品牌列时,我可以添加一个唯一约束,它会抛出一个异常,我可以用它再次递增它,直到它起作用。
第四:现在我找到了另一种可行的方法。我不保存订购号码。相反,我添加一个列,其中包含下一个元素的id。这意味着订单中的每个请求都有一个Join,但我知道这个表没有很多行,所以性能并不重要。订单更改时的更新也会更容易。那么解决这个问题的正确方法是什么。当我必须在订单更改时更新所有对象时,我还必须解决问题。
答案 0 :(得分:1)
使用mysql触发器可以让你非常直接地检查另一个SO question。
答案 1 :(得分:0)
你试过@OrderColumn吗? JPA提供商的业务如何在有序列表的情况下处理并发(我正在考虑一些约束)。有序树结构的Here示例。
您也可以尝试使用JPA locks。请参阅PESSIMISTIC
。
答案 2 :(得分:0)
我的问题的另一个解决方案是使订单列和品牌列都是UNIQUE(ADD CONSTRAINT UNIQUE(订单,品牌))。然后在特定品牌中只能有一个订单号。然后我将不得不对ConstraintViolationException做出反应,并使用新值重做插入。但我感谢它不是很好,因为你不确切知道constraintViolationException是否真的是由于Unique约束或其他一些Constraint Violation