简体   繁体   English

如何保存表顺序并防止并发问题

[英]How to save the order of a table and prevent concurrency issues

I have the following problem I have to save the order of some elements in a table. 我有以下问题,我必须将某些元素的顺序保存在表中。 This is done by a order number. 这是通过订单号完成的。 So the first element has ordering 1 and the tenth the ordering 10 etc. Also I have a brand value saved, which means the ordering is only inside all rows of one brand. 因此,第一个元素的排序为1,第十个元素的排序为10,依此类推。另外,我还保存了品牌价值,这意味着该排序仅在一个品牌的所有行中。 My configuration is Spring 3.1 with Hibernate 4.1.6 and Spring Data, I also use the JPA interface, underlying is a Mysql Database. 我的配置是带有Hibernate 4.1.6和Spring Data的Spring 3.1,我也使用JPA接口,底层是Mysql数据库。

I have right now a save method which gets the maximum value by a namedquery. 我现在有一个save方法,该方法通过namedquery获取最大值。 Then increments the value by one. 然后将值增加一。 And now sets the value with the object setter. 现在,使用对象设置器设置值。 Then saves it. 然后保存。

    if(tag.getOrdering()==0) {
        int newOrderingNumber = tagRepository.getMaximumOrderingNumber();
        newOrderingNumber++;
        if(LOGGER.isDebugEnabled()) {
            LOGGER.debug("Next Ordering Number for Tag is " + newOrderingNumber);
        }
        tag.setOrdering(newOrderingNumber);
    }

Here I have a problem what would happen if two threads are doing this at the same time. 在这里,我有一个问题,如果两个线程同时执行此操作会发生什么。 They would both save the same value. 它们都将保存相同的值。 But one would have to increment twice. 但是必须增加两次。 My question is how could I prevent this. 我的问题是如何防止这种情况。 First I tried to do something with the isolation level of the spring transaction, but JPA doenst know transaction levels and the ways I found how I could extend the jpadialect like here ( http://amitstechblog.wordpress.com/2011/05/31/supporting-custom-isolation-levels-with-jpa/ ) But that didnt work, my Connection was always readonly the readOnly=false flag was not set correctly and I didnt find out what was wrong. 首先,我尝试对春季交易的隔离级别做一些事情,但是JPA确实了解交易级别以及我发现如何扩展jpadialect的方法,例如此处( http://amitstechblog.wordpress.com/2011/05/31 / supporting-custom-isolation-levels-with-jpa / ),但没有奏效,我的Connection始终为只读状态,未正确设置readOnly = false标志,我也没有发现问题所在。 Also I think that wouldn`t solve my problem. 我也认为这不会解决我的问题。

Then I tried to work with a @Version Property, but this doesnt work because I do not work on one object instance. 然后,我尝试使用@Version属性,但这不起作用,因为我不在一个对象实例上工作。 The two threads are working on two different rows, so the versioning doesnt solve the problem. 这两个线程在两个不同的行上工作,因此版本控制无法解决问题。

So now I see four different approaches. 所以现在我看到了四种不同的方法。

First: I could use a synchronize lock object inside my code to let one thread wait for the other to free the lock on the object 第一:我可以在代码中使用同步锁对象,让一个线程等待另一个线程释放该对象上的锁

Second: I could acquire a full table lock, which I dont know how to do with hibernate and it also seems oversized to block the complete table. 第二:我可以获得一个全表锁,我不知道该如何使用休眠方式,并且它似乎也太大了,无法阻塞整个表。

Third: When I wouldnt have the brand column inside which the ordering could be the same, I could add a Unique constraint which would throw an Exception which I can use to increment it once again, til it works. 第三:当我不会在其中有相同顺序的brand列时,我可以添加一个Unique约束,该约束将抛出一个Exception,我可以使用该异常再次对其进行递增,直到它起作用为止。

Fourth: Right now I found an additional way, which could work. 第四:现在我找到了另一种可行的方法。 I dont save an ordering number. 我不保存订购号。 Instead I add a column which contains the id of the next element in order. 相反,我添加了按顺序包含下一个元素的ID的列。 This would mean that there is a Join in every request with the order, but I know that this table has not many rows, so the performance doesnt really matter. 这意味着每个请求中都包含一个Join顺序,但是我知道该表没有很多行,因此性能并不重要。 Also the updating when the order changes would be much easier. 同样,当订单更改时更新将更加容易。

So what would be the right way to solve this problem. 那么什么是解决这个问题的正确方法。 I also have to solve the problem when I have to update all objects when the ordering is changed. 当更改顺序时必须更新所有对象时,我也必须解决该问题。

使用mysql触发器应该可以使您进行直接检查其他SO问题

Have you tried @OrderColumn ? 您是否尝试过@OrderColumn It is business of JPA provider how to deal with concurrency in case of ordered list (I am thinking by some constraints). 在有序列表的情况下如何处理并发是JPA提供者的业务(我在考虑一些约束)。 Here example of ordered tree structure. 是有序树结构的示例。

Also you may try to use JPA locks . 您也可以尝试使用JPA锁 See for PESSIMISTIC . PESSIMISTIC

An additional solution for my problem would be to make the order column and the brand column both UNIQUE ( ADD CONSTRAINT UNIQUE(order,brand) ) . 解决我的问题的另一种方法是使order列和brand列都为UNIQUE(ADD CONSTRAINT UNIQUE(order,brand))。 Then there could be one order number only once inside a specific brand. 那么在一个特定品牌内可能只有一个订单号。 Then I would have to react to a ConstraintViolationException, and redo the insert with new values. 然后,我将不得不对ConstraintViolationException做出反应,并使用新值重做插入。 But I thank its not very nice, because you dont know exactly if the constraintViolationException is really due to the Unique constraint or some other Constraint Violation 但我要感谢它不是很好,因为您不知道ConstrainViolationException是否真的是由于Unique约束或其他一些Constraint Violation造成的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM