我的代码在很长一段时间内都运行良好,但经过一些重构后,我注意到我突然无法保存Group
个对象。
我遇到了可怕的Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
错误。谷歌搜索后当然找到this StackOverflow question,但它并没有帮助我,因为我没有同时做任何事情。
通过我的重构后,我发现的唯一区别就是这种变化。
之前:
final Collection<Sample> allByBarcode = sampleService.byBarcode(groupRequest.getSamples(), currentUser);
if (!allByBarcode.isEmpty()) {
Group group = new Group();
group.setName(groupRequest.getName());
group.setSamples(allByBarcode);
group.setType(groupRequest.getType());
group.setOwner(currentUser);
group = repository.save(group);
return Optional.ofNullable(group);
}
在重构之后(不记得原因),它变成了:
final Collection<Sample> allByBarcode = sampleService.byBarcode(groupRequest.getSamples(), currentUser);
if (!allByBarcode.isEmpty()) {
Group group = new Group();
group.setName(groupRequest.getName());
group.setSamples(new HashSet<>(allByBarcode));
group.setType(groupRequest.getType());
group.setOwner(currentUser);
group = repository.save(group);
return Optional.ofNullable(group);
}
将其改回原版后,每次都突然重新开始工作,没有任何错误。
有人可以解释一下这个错误的原因是什么,因为这实际上是代码中唯一能让它再次起作用的区别?
更新1:
我尝试了另一种变体:
Group group = new Group();
group.setName(groupRequest.getName());
group.setSamples(new ArrayList<>(allByBarcode));
group.setType(groupRequest.getType());
group.setOwner(currentUser);
group = repository.save(group);
注意ArrayList
而不是HashSet
- 由于某种原因,此代码有效。
我也试过LinkedList
也可以。
有什么想法吗?
更新2:
堆栈跟踪如下: 我已将其删除以删除大量与Spring和Tomcat相关的跟踪。
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.ObjectOptimisticLockingFailureException: Object of class [uk.ac.sanger.mig.aker.domain.Group] with identifier [93]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [uk.ac.sanger.mig.aker.domain.Group#93]] with root cause
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [uk.ac.sanger.mig.aker.domain.Group#93]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2541)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3285)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3183)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3525)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:159)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:521)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy116.createGroup(Unknown Source)
at uk.ac.sanger.mig.aker.controllers.GroupController.store(GroupController.java:107)
答案 0 :(得分:4)
在新代码中,您要创建一个新的HashSet
,其中包含Sample
集合中的所有allByBarcode
元素。
我认为这里引发的问题是因为会话没有保留这些元素,因为它们是添加到new HashSet()
实例的新对象,并且它们并未真正保存在会话中,它解释了Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
Exception
但allByBarcode
元素来自您的服务,因此会话持久 识别。
而且我不知道是什么需要设置一个新的HashSet
实例,其中元素应该被会话保存(持久化)(这将抛出Exception
因为您尝试使用现有标识符保存元素,而设置已保存的元素效率更高,更安全,所以更好地使用:
group.setSamples(allByBarcode);
答案 1 :(得分:1)
我认为问题是你的集合中有一些重复的对象allByBarcode,当你将你的集合包装在一个不允许重复的HashSet中时会消失。之后会发生什么:您的存储库试图多次保存同一个对象。
答案 2 :(得分:0)
由于您已经将样本对象初始化为HashSet
,您可以尝试这样做而不是再次初始化它。
group.getSamples().addAll(allByBarcode);