spring 在不同事务中删除->保存组合时出现意外的重复主键

gupuwyp2  于 2024-01-05  发布在  Spring
关注(0)|答案(1)|浏览(143)

我需要保存非常大的实体的新示例。为此,我使用propagation=REQUIRED_NEW删除此实体,然后在新事务中为同一项目保存新实体。由于此操作,我收到异常,其中一个相关实体无法保存,因为相同的主键仍在数据库中。意外的是,所有实体(包括异常中提到的实体)保存正确。为什么我收到这个错误,我应该怎么做来修复它?收到链接实体上的错误(当删除关联实体,然后创建新实体时)。

异常

  1. org.springframework.dao.DataIntegrityViolationException: could not execute statement [ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности "uk_2ds6ia48b1ea56u8qpv52qukq"
  2. Подробности: Ключ "(project_id)=(b0d576ff-bca8-4ea3-9c1e-04db309dccb3)" уже существует.] [insert into schemes (offset_x,offset_y,project_id,version,zoom) values (?,?,?,?,?)]; SQL [insert into schemes (offset_x,offset_y,project_id,version,zoom) values (?,?,?,?,?)]; constraint [null]
  3. at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:269)
  4. at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:229)
  5. at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
  6. at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
  7. at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:243)
  8. at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
  9. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
  10. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751)
  11. at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703)
  12. at ru.mpei.dcse.repository.SchemeRepository$$SpringCGLIB$$0.save(<generated>)
  13. at ru.mpei.dcse.service.data.SchemeService.save(SchemeService.java:25)
  14. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  15. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  16. at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  17. at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  18. at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
  19. at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
  20. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
  21. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751)
  22. at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
  23. at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391)
  24. at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
  25. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
  26. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751)
  27. at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703)
  28. at ru.mpei.dcse.service.data.SchemeService$$SpringCGLIB$$0.save(<generated>)
  29. at ru.mpei.dcse.service.facade.SchemeFacade.updateProjectScheme(SchemeFacade.java:49)
  30. at ru.mpei.dcse.service.facade.SchemeFacade.save(SchemeFacade.java:33)
  31. at ru.mpei.dcse.controller.SchemeController.save(SchemeController.java:29)
  32. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  33. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  34. at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  35. at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  36. at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
  37. at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
  38. at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
  39. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
  40. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
  41. at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
  42. at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081)
  43. at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)
  44. at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)
  45. at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)
  46. at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590)
  47. at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
  48. at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
  49. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
  50. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
  51. at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
  52. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
  53. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
  54. at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
  55. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  56. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
  57. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
  58. at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
  59. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  60. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
  61. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
  62. at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
  63. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
  64. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
  65. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
  66. at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
  67. at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
  68. at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
  69. at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
  70. at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
  71. at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
  72. at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340)
  73. at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391)
  74. at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
  75. at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896)
  76. at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744)
  77. at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
  78. at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
  79. at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
  80. at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  81. at java.base/java.lang.Thread.run(Thread.java:840)
  82. Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement [ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности "uk_2ds6ia48b1ea56u8qpv52qukq"
  83. Подробности: Ключ "(project_id)=(b0d576ff-bca8-4ea3-9c1e-04db309dccb3)" уже существует.] [insert into schemes (offset_x,offset_y,project_id,version,zoom) values (?,?,?,?,?)]
  84. at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:95)
  85. at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56)
  86. at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:108)
  87. at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:278)
  88. at org.hibernate.id.insert.GetGeneratedKeysDelegate.performInsert(GetGeneratedKeysDelegate.java:107)
  89. at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorPostInsertSingleTable.execute(MutationExecutorPostInsertSingleTable.java:100)
  90. at org.hibernate.persister.entity.mutation.InsertCoordinator.doStaticInserts(InsertCoordinator.java:171)
  91. at org.hibernate.persister.entity.mutation.InsertCoordinator.coordinateInsert(InsertCoordinator.java:112)
  92. at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2780)
  93. at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
  94. at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:676)
  95. at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:291)
  96. at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:272)
  97. at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:322)
  98. at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:363)
  99. at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:277)
  100. at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:180)
  101. at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:140)
  102. at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:175)
  103. at org.hibernate.event.internal.DefaultPersistEventListener.persist(DefaultPersistEventListener.java:93)
  104. at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:77)
  105. at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:54)
  106. at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
  107. at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:755)
  108. at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:739)
  109. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  110. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  111. at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  112. at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  113. at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:360)
  114. at jdk.proxy2/jdk.proxy2.$Proxy121.persist(Unknown Source)
  115. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  116. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  117. at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  118. at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  119. at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311)
  120. at jdk.proxy2/jdk.proxy2.$Proxy121.persist(Unknown Source)
  121. at ru.mpei.dcse.repository.SchemeRepository.save(SchemeRepository.java:21)
  122. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  123. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  124. at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  125. at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  126. at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
  127. at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
  128. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
  129. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751)
  130. at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
  131. ... 73 more
  132. Caused by: org.postgresql.util.PSQLException: ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности "uk_2ds6ia48b1ea56u8qpv52qukq"
  133. Подробности: Ключ "(project_id)=(b0d576ff-bca8-4ea3-9c1e-04db309dccb3)" уже существует.
  134. at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2676)
  135. at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2366)
  136. at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:356)
  137. at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:496)
  138. at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:413)
  139. at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:190)
  140. at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:152)
  141. at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
  142. at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
  143. at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:275)
  144. ... 116 more

字符串
facade类的坏方法(没有transaction),第4-7块:

schemeService.delete

  1. @Transactional(propagation = Propagation.REQUIRES_NEW)
  2. public boolean delete(String projectId) {
  3. return this.repository.delete(projectId);
  4. }

schemeRepository.delte

  1. public boolean delete(String projectId) {
  2. return this.entityManager.createQuery("DELETE FROM Scheme s WHERE s.projectInfo.id = :projectId")
  3. .setParameter("projectId", projectId)
  4. .executeUpdate() > 0;
  5. }

schemeService.保存

  1. @Transactional(propagation = Propagation.REQUIRES_NEW)
  2. public void save(Scheme scheme) {
  3. this.repository.save(scheme);
  4. }

schemeRepository.保存

  1. public void save(Scheme scheme) {
  2. this.entityManager.persist(scheme);
  3. }

方案

  1. @Entity
  2. @Table(name = "schemes")
  3. @Getter@Setter
  4. @NoArgsConstructor
  5. @AllArgsConstructor
  6. public class Scheme implements SelfUpdatable<Scheme> {
  7. @Id
  8. @GeneratedValue(strategy = GenerationType.IDENTITY)
  9. private Long id;
  10. @Column(name = "offset_x")
  11. private double offsetX;
  12. @Column(name = "offset_y")
  13. private double offsetY;
  14. private double zoom;
  15. private double version;
  16. @OneToMany(
  17. mappedBy = "scheme",
  18. cascade = CascadeType.ALL,
  19. orphanRemoval = true
  20. )
  21. private List<EquipmentNode> nodes = new ArrayList<>();
  22. @OneToMany(
  23. mappedBy = "scheme",
  24. cascade = CascadeType.ALL,
  25. orphanRemoval = true
  26. )
  27. private List<Link> links = new ArrayList<>();
  28. @OneToOne
  29. @OnDelete(action = OnDeleteAction.CASCADE)
  30. @JoinColumn(name = "project_id")
  31. private ProjectInfo projectInfo;
  32. }

项目信息

  1. @Entity
  2. @Getter@Setter
  3. @NoArgsConstructor
  4. @Table(name = "project_info")
  5. public class ProjectInfo {
  6. @Id
  7. private String id;
  8. private String name;
  9. private String owner;
  10. @Convert(converter =ListAttributeConverter.class)
  11. private List<String> applications;
  12. @OneToOne(
  13. mappedBy = "projectInfo",
  14. cascade = CascadeType.ALL,
  15. fetch = FetchType.EAGER
  16. )
  17. private Scheme scheme;
  18. @OneToOne(
  19. mappedBy = "projectInfo",
  20. cascade = CascadeType.ALL,
  21. fetch = FetchType.EAGER
  22. )
  23. private CalculationsSettings settings;
  24. @OneToMany(
  25. fetch = FetchType.LAZY,
  26. cascade = CascadeType.ALL,
  27. orphanRemoval = true
  28. )
  29. private List<GeneratedScenario> generatedScenarios;
  30. }

友情链接

  1. @Entity
  2. @Getter@Setter
  3. @NoArgsConstructor
  4. @AllArgsConstructor
  5. @Table(name = "links")
  6. public class Link implements SelfUpdatable<Link> {
  7. @Id
  8. @Column(nullable = false, unique = true)
  9. private String id;
  10. private String alignmentType;
  11. private String sourceEquipmentId;
  12. private String sourcePortId;
  13. private String targetEquipmentId;
  14. private String targetPortId;
  15. @OneToMany(mappedBy = "link", cascade = CascadeType.ALL, orphanRemoval = true)
  16. private List<Point> points;
  17. @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  18. @OnDelete(action = OnDeleteAction.CASCADE)
  19. @JoinColumn(name = "scheme_id")
  20. private Scheme scheme;


我试图改变传播级别,使用存储库来对抗服务。

7gyucuyw

7gyucuyw1#

当你删除实体时,你需要刷新,因为当你保存实体时,你的外部事务还没有提交,它只在第一个事务的上下文中被删除。

相关问题