升级 Spring Boot 应用程序后出现 Hibernate SQLINtegrityConstraintViolation/重复数据输入问题

问题描述 投票:0回答:1

我正在尝试从 springBoot 2.5 迁移到 2.7,并注意到有时我会遇到 重复数据输入时的 SQLINtegrityConstraintViolation

2024-05-06 17:19:30.929  WARN 6556 --- [nio-9012-exec-2] o.m.jdbc.message.server.ErrorPacket      : Error: 1062-23000: Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'
2024-05-06 17:19:30.930  INFO 6556 --- [nio-9012-exec-2] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements
2024-05-06 17:19:30.931 ERROR 6556 --- [nio-9012-exec-2] o.h.e.jdbc.batch.internal.BatchingBatch  : HHH000315: Exception executing batch [java.sql.BatchUpdateException: (conn=9469435) Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'], SQL: update t_instance set ask=?, ask1=?, ask2=?, assetType=?, attrChangeId=?, bid=?, bid1=?, bid2=?, bkgdref=?, closing=?, comments=?, contributor=?, createdby=?, crud=?, curvespreadask=?, curvespreadbid=?, curvespreadmid=?, date1=?, date2=?, dimChangeId=?, distributioncount=?, faquotation=?, hasSubRates=?, historicclose=?, holidayflag=?, instanceupdatedby=?, instanceupdateddate=?, intraflag=?, last=?, lockstatus=?, manualuploadfilename=?, maturitysource=?, mid=?, mid1=?, mid2=?, ops=?, pricingsource=?, quoteunits=?, radCheck=?, reasoncodeid=?, recorddate=?, resrccnt=?, singleContributor=?, spread=?, srccurrency=?, srcfavor=?, srcstrike=?, statusid=?, subRateSnapId=?, T_1_DATE=?, trailingdate=?, triggerOrion=?, txId=?, updatedby=?, updateddate=?, usedInfo=?, violationid=?, workingdayflag=?, yieldask=?, yieldbid=?, yieldmid=? where locationId=? and rateId=?
2024-05-06 17:19:30.931  WARN 6556 --- [nio-9012-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1062, SQLState: 23000
2024-05-06 17:19:30.931 ERROR 6556 --- [nio-9012-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : (conn=9469435) Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'
2024-05-06 17:19:30.941 ERROR 6556 --- [nio-9012-exec-2] c.d.r.u.service.impl.TestingServiceImpl  : error is could not execute batch; SQL [update t_instance set ask=?, ask1=?, ask2=?, assetType=?, attrChangeId=?, bid=?, bid1=?, bid2=?, bkgdref=?, closing=?, comments=?, contributor=?, createdby=?, crud=?, curvespreadask=?, curvespreadbid=?, curvespreadmid=?, date1=?, date2=?, dimChangeId=?, distributioncount=?, faquotation=?, hasSubRates=?, historicclose=?, holidayflag=?, instanceupdatedby=?, instanceupdateddate=?, intraflag=?, last=?, lockstatus=?, manualuploadfilename=?, maturitysource=?, mid=?, mid1=?, mid2=?, ops=?, pricingsource=?, quoteunits=?, radCheck=?, reasoncodeid=?, recorddate=?, resrccnt=?, singleContributor=?, spread=?, srccurrency=?, srcfavor=?, srcstrike=?, statusid=?, subRateSnapId=?, T_1_DATE=?, trailingdate=?, triggerOrion=?, txId=?, updatedby=?, updateddate=?, usedInfo=?, violationid=?, workingdayflag=?, yieldask=?, yieldbid=?, yieldmid=? where locationId=? and rateId=?]; constraint [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute batch
2024-05-06 17:19:30.944 ERROR 6556 --- [nio-9012-exec-2] c.d.r.u.service.impl.TestingServiceImpl  : full msg

org.springframework.dao.DataIntegrityViolationException: could not execute batch; SQL [update t_instance set ask=?, ask1=?, ask2=?, assetType=?, attrChangeId=?, bid=?, bid1=?, bid2=?, bkgdref=?, closing=?, comments=?, contributor=?, createdby=?, crud=?, curvespreadask=?, curvespreadbid=?, curvespreadmid=?, date1=?, date2=?, dimChangeId=?, distributioncount=?, faquotation=?, hasSubRates=?, historicclose=?, holidayflag=?, instanceupdatedby=?, instanceupdateddate=?, intraflag=?, last=?, lockstatus=?, manualuploadfilename=?, maturitysource=?, mid=?, mid1=?, mid2=?, ops=?, pricingsource=?, quoteunits=?, radCheck=?, reasoncodeid=?, recorddate=?, resrccnt=?, singleContributor=?, spread=?, srccurrency=?, srcfavor=?, srcstrike=?, statusid=?, subRateSnapId=?, T_1_DATE=?, trailingdate=?, triggerOrion=?, txId=?, updatedby=?, updateddate=?, usedInfo=?, violationid=?, workingdayflag=?, yieldask=?, yieldbid=?, yieldmid=? where locationId=? and rateId=?]; constraint [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute batch
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:276)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:241)
    at jdk.proxy2/jdk.proxy2.$Proxy257.saveAll(Unknown Source)
    at com.mycompany.trax.uiservice.service.impl.TestingServiceImpl.testingLoop(TestingServiceImpl.java:38)
    at com.mycompany.trax.uiservice.service.impl.TestingServiceImpl$$FastClassBySpringCGLIB$$ff8f61f1.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:792)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:707)
    at com.mycompany.trax.uiservice.service.impl.TestingServiceImpl$$EnhancerBySpringCGLIB$$323b0328.testingLoop(<generated>)
    at com.mycompany.trax.uiservice.controller.TestingController.test(TestingController.java:27)
    at com.mycompany.trax.uiservice.controller.TestingController$$FastClassBySpringCGLIB$$3c8d5603.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:792)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:707)
    at com.mycompany.trax.uiservice.controller.TestingController$$EnhancerBySpringCGLIB$$8e3c1a27.test(<generated>)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:529)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
    at com.mycompany.trax.uiservice.filter.TimeZoneFilter.doFilterInternal(TimeZoneFilter.java:109)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:928)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1794)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute batch
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:109)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:37)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:135)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.doExecuteBatch(BatchingBatch.java:110)
    at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.execute(AbstractBatchImpl.java:153)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:198)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:633)
    at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
    at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:344)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1407)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:489)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3303)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2438)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:449)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562)
    ... 109 common frames omitted
Caused by: java.sql.BatchUpdateException: (conn=9469435) Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'
    at org.mariadb.jdbc.export.ExceptionFactory.createBatchUpdate(ExceptionFactory.java:181)
    at org.mariadb.jdbc.ClientPreparedStatement.executeBatchBulk(ClientPreparedStatement.java:179)
    at org.mariadb.jdbc.ClientPreparedStatement.executeInternalPreparedBatch(ClientPreparedStatement.java:115)
    at org.mariadb.jdbc.ClientPreparedStatement.executeBatch(ClientPreparedStatement.java:466)
    at com.zaxxer.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:127)
    at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeBatch(HikariProxyPreparedStatement.java)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:125)
    ... 129 common frames omitted
Caused by: java.sql.BatchUpdateException: (conn=9469435) Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'
    at org.mariadb.jdbc.export.ExceptionFactory.createBatchUpdate(ExceptionFactory.java:215)
    at org.mariadb.jdbc.client.impl.StandardClient.executePipeline(StandardClient.java:637)
    at org.mariadb.jdbc.ClientPreparedStatement.executeBatchBulk(ClientPreparedStatement.java:148)
    ... 134 common frames omitted
Caused by: java.sql.SQLIntegrityConstraintViolationException: (conn=9469435) Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'
    at org.mariadb.jdbc.export.ExceptionFactory.createException(ExceptionFactory.java:290)
    at org.mariadb.jdbc.export.ExceptionFactory.create(ExceptionFactory.java:370)
    at org.mariadb.jdbc.message.ClientMessage.readPacket(ClientMessage.java:134)
    at org.mariadb.jdbc.client.impl.StandardClient.readPacket(StandardClient.java:872)
    at org.mariadb.jdbc.client.impl.StandardClient.readResults(StandardClient.java:811)
    at org.mariadb.jdbc.client.impl.StandardClient.readResponse(StandardClient.java:730)
    at org.mariadb.jdbc.client.impl.StandardClient.executePipeline(StandardClient.java:571)
    ... 135 common frames omitted

重复实际上是由从 t_instance 复制到 h_instance 的触发器引起的,在调试时,我们注意到,如果系统尝试更新 15 条记录,它实际上更新了 1 条记录 14-15 次, 并通过以下方式将字段复制到 h_instance数据库触发器具有相同的rateid,这将导致触发器抛出错误。

抛出此错误的代码在这里,这是一个检索并立即保存记录的简单方法。通常此方法每次触发时会保存 5 - 100 条记录。它不包含重复项,因为传递的集合 (rateIds) 通常是一个 Set。

@Autowired
private InstanceRepository instanceRepo;

@Transactional
public void testingLoop(){
    try {
        long[] instances = {105497181, 105285213, 105321169}; //500 records, here only shown 3...
        List<Long> instanceIdList = Arrays.stream(instances).boxed().collect(Collectors.toList());
        List<Instance> items = instanceRepo.findByRateIdInAndLocationid(instanceIdList, 101);
        if (items != null && !items.isEmpty()) {
            logger.info("records found:{}", items.size());
            for (Instance item : items) {
                item.setStatusid(10);
                item.setAsk("1.23");
                item.setBid("1.23");
                item.setMid("1.23");
            }
            instanceRepo.saveAll(items);
        }
    }catch(Exception e){
        logger.error("error is {}",e.getMessage());
        logger.error("full msg",e);
    }
}

数据源

@Configuration
@EnableTransactionManagement
@EnableBatchProcessing
@EnableAutoConfiguration
@EnableJpaRepositories(basePackages = {
    "com.mycompany.trax.db.reliable.repo"}, entityManagerFactoryRef = "reliableEntityManagerFactory", transactionManagerRef = "reliableTransactionManager")
public class ReliableDS {

  private final Logger logger = RMSLogger.getLogger(this.getClass());
 

  @Autowired
  private ReliableEntityInterceptor entityInterceptor;
  
  @Bean(name = "reliableDataSource")
  @ConfigurationProperties(prefix = "spring.datasource.reliable")
  public DataSource reliableDataSource() {
     //DataSource  ds = DataSourceBuilder.create().build();

      DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
      dataSourceBuilder.driverClassName("org.mariadb.jdbc.Driver");
     return dataSourceBuilder.build();
  }

  @Bean(name = "reliableEntityManagerFactory")
  public LocalContainerEntityManagerFactoryBean reliableEntityManagerFactory() {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    // show hibernate generated SQl
    //vendorAdapter.setShowSql(true);

    Map<String, Object> jpaProperties = new HashMap<String, Object>();
    if(entityInterceptor != null) {
      //jpaProperties.put("hibernate.session_factory.interceptor", entityInterceptor);
      jpaProperties.put("hibernate.order_inserts", Boolean.TRUE);
      jpaProperties.put("hibernate.order_updates", Boolean.TRUE);
      
      jpaProperties.put("hibernate.jdbc.batch_size", 20);
      jpaProperties.put("hibernate.jdbc.fetch_size", 400);
    }
    
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(reliableDataSource());
    em.setJpaPropertyMap(jpaProperties);
    em.setPackagesToScan("com.mycompany.trax.db.reliable.entity","com.mycompany.trax.db.reliable.modelentity");
    em.setJpaVendorAdapter(vendorAdapter);
    return em;
  }

  @Bean(name = "reliableTransactionManager")
  public PlatformTransactionManager  reliableTransactionManager() {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(reliableEntityManagerFactory().getObject());
    return transactionManager;
  }

  @Bean(name="reliableJdbcTemplate")
  public NamedParameterJdbcTemplate jdbcTemplate(){
     return new NamedParameterJdbcTemplate(reliableDataSource());
  }
}

实体:

@Data
@Entity
@Table(name = "t_instance")
@IdClass(InstancePK.class)
@EntityListeners(InstanceListener.class)
@NoArgsConstructor
public class Instance implements Serializable {

  private static final long serialVersionUID = 1L;

  /** The Attr change id. */
  private String attrChangeId;

  /** The Used info. */
  @JsonProperty("usedinfo")
  public String usedInfo;

  @Id
  @Column(name = "rateId",updatable=false)
  private Long rateId;

  @Id
  @Column(name = "locationId",updatable=false)
  private Integer locationid;

  private String ask;
  //and another 50 more fields.... 
}

我们还注意到,如果我们只使用 save() (逐一保存实体),或者将批量大小设置为 1,它不会返回任何问题。

知道为什么带有 saveAll() 的 spring 批处理在这里不起作用吗?

我还启用了休眠日志(使用活页夹),并且我只能看到数据库中存在问题的rateid的1个更新

其他信息:

  • 休眠版本:5.6.15_Final
  • mariadb 版本:10.6
  • Spring Boot 2.7
  • mariadb jdbc 客户端版本 3.3.3

触发: 更新前 创建定义器=

USERADMIN
@
%
在每行开始更新
TRG_BU_T_INSTANCE
之前触发
t_instance
设置新的.ATTRCHANGEID=UUID(); 结束

更新后(简化 - 仍然有问题,详细信息 创建定义器=

USERADMIN
@
%
在每行开始更新
TRG_AU_T_INSTANCE
后触发
t_instancetest
插入
t_datalog
(
RateId
,
CreatedDate
) 值 (OLD.RATEID, sysdate()); 结束

准备声明: n.t.d.l.l.SLF4JQueryLoggingListener : {"name":"reliableDataSource", "connection":3, "time":13, "success":true, "type":"Prepared", "batch":true, "querySize":1, “batchSize”:7,“查询”:[“更新t_instancetest设置ask=?,bid=?,createdby=?,crud=?,instanceupdateddate=?,locationId=?,mid=?,updatedby=?,updateddate=?其中 locationid=? 和rateId=?"], "params":[["116.13","12.23","SYSTEM","U","2024-05-10 12:31:59.665","101", "7181","娜迦","2024-05-10 12:03:55.0","101","7181"],["116.13","12.23","系统","U","2024- 05-10 12:31:59.665","101","7239","娜迦","2024-05-10 12:03:55.0","101","7239"],["116.13"," 12.23","系统","U","2024-05-10 12:31:59.665","101","7254","纳迦","2024-05-10 12:03:55.0"," 101","7254"],["116.13","12.23","系统","U","2024-05-10 12:31:59.665","101","7265","纳迦", "2024-05-10 12:03:55.0","101","7265"],["116.13","12.23","系统","U","2024-05-10 12:31:59.665 ","101","7370","娜迦","2024-05-10 12:03:55.0","101","7370"],["116.13","12.23","系统"," U","2024-05-10 12:31:59.665","101","7453","纳迦","2024-05-10 12:03:55.0","101","7453"], [“116.13”,“12.23”,“系统”,“U”,“2024-05-10 12:31:59.665”,“101”,“7643”,“纳迦”,“2024-05-10 12: 03:55.0","101","7643"]]}

我在下面的答案中包含了 mariadb 日志,因为正文限制为 30k 个字符。

hibernate spring-data-jpa mariadb
1个回答
0
投票

不是真正的答案。添加观察到但无法放入 30k 问题主体的行为。

似乎是由触发器引起的,因为虽然preparedstatement看起来不错,但mariadb日志不同。看起来它可以重复运行触发器 7 次。如果我们松开扳机,情况就会恢复正常。

 #240509 17:27:01 server id 2  end_log_pos 127297238 CRC32 0x5e6a5fa7   Write_rows: table id 3067 flags: STMT_END_F
### UPDATE `rms_reliabledb`.`t_instance`
### WHERE
###   @1=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2='12.23' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
###   @3='116.13' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
###   @4='' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
###   @5='2024-05-09 16:49:54.962888' /* DATETIME(6) meta=6 nullable=1 is_null=0 */
###   @6='2024-05-09 17:22:52.812000' /* DATETIME(6) meta=6 nullable=1 is_null=0 */
###   @7='naga' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
###   @8='U' /* VARSTRING(3) meta=3 nullable=1 is_null=0 */
###   @9='SYSTEM' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
###   @10='naga' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
###   @11=101 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @1=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2='12.23' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
###   @3='116.13' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
###   @4='7181' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
###   @5='2024-05-09 16:49:54.962888' /* DATETIME(6) meta=6 nullable=1 is_null=0 */
###   @6='2024-05-09 17:27:01.116000' /* DATETIME(6) meta=6 nullable=1 is_null=0 */
###   @7='naga' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
###   @8='U' /* VARSTRING(3) meta=3 nullable=1 is_null=0 */
###   @9='SYSTEM' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
###   @10='naga' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
###   @11=101 /* INT meta=0 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
###   @1=98 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
###   @1=99 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
###   @1=100 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
###   @1=101 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
###   @1=102 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
###   @1=103 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
###   @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
# Number of rows: 7
# at 127297238
#240509 17:27:01 server id 2  end_log_pos 127297269 CRC32 0xd7928418    Xid = 205571784
COMMIT/*!*/;

下面还有长触发器(更新之前),后来被简化为仅插入数据日志。

    CREATE DEFINER=`USERADMIN`@`%` TRIGGER `TRG_AU_T_INSTANCE` AFTER UPDATE ON `t_instance` FOR EACH ROW BEGIN
DECLARE v_current_time DATETIME(6);
DECLARE v_sys_eff_end_dt DATETIME;
DECLARE v_attr_json_str  LONGTEXT;

SET  v_current_time= CURTIME(6);

SET  v_sys_eff_end_dt='8888-12-31 23:59:59';
SET  v_attr_json_str = CONCAT('{ "ASK":"',  IFNULL(NEW.ASK,''),                                                
                                            '","BID":"',IFNULL(NEW.BID,''),                                            
                                            '","MID":"',IFNULL(NEW.MID,''),
                                            '","YIELDBID":"',IFNULL(NEW.YIELDBID,''),
                                            '","YIELDMID":"',IFNULL(NEW.YIELDMID,''),
                                            '","YIELDASK":"',IFNULL(NEW.YIELDASK,''),
                                            '","MATURITYSOURCE":"',IFNULL(NEW.MATURITYSOURCE,''),
                                            '","LAST":"',IFNULL(NEW.LAST,''),
                                            '","CLOSING":"',IFNULL(NEW.CLOSING,''),
                                            '","PRICINGSOURCE":"',IFNULL(NEW.PRICINGSOURCE,''),
                                            '","HISTORICCLOSE":"',IFNULL(NEW.HISTORICCLOSE,''),
                                            '","CURVESPREADASK":"',IFNULL(NEW.CURVESPREADASK,''),
                                            '","CURVESPREADBID":"',IFNULL(NEW.CURVESPREADBID,''),
                                            '","CURVESPREADMID":"',IFNULL(NEW.CURVESPREADMID,''),
                                            '","BKGDREF":"',IFNULL(NEW.BKGDREF,''),
                                            '","MANUALUPLOADFILENAME":"',IFNULL(NEW.MANUALUPLOADFILENAME,''),
                                            '","CONTRIBUTOR":"',IFNULL(NEW.CONTRIBUTOR,''),
                                            '","MID1":"',IFNULL(NEW.MID1,''),
                                            '","MID2":"',IFNULL(NEW.MID2,''),
                                            '","SRCFAVOR":"',IFNULL(NEW.SRCFAVOR,''),
                                            '","ASK1":"',IFNULL(NEW.ASK1,''),
                                            '","ASK2":"',IFNULL(NEW.ASK2,''),
                                            '","BID1":"',IFNULL(NEW.BID1,''),
                                            '","BID2":"',IFNULL(NEW.BID2,''),
                                            '","DATE1":"',IFNULL(NEW.DATE1,''),
                                            '","QUOTEUNITS":"',IFNULL(NEW.QUOTEUNITS,''),
                                            '","DATE2":"',IFNULL(NEW.DATE2,''),
                                            '","FAQUOTATION":"',IFNULL(NEW.FAQUOTATION,''),
                                            '","SRCSTRIKE":"',IFNULL(NEW.SRCSTRIKE,''),
                                            '","SRCCURRENCY":"',IFNULL(NEW.SRCCURRENCY,''),
                                            '","RESRCCNT":"',IFNULL(NEW.RESRCCNT,''),
                                            '","SPREAD":"',IFNULL(NEW.SPREAD,''),
                                            '","SINGLECONTRIBUTOR":"',IFNULL(NEW.SINGLECONTRIBUTOR,''),
                                            '","TRAILINGDATE":"',IFNULL(NEW.TRAILINGDATE,''),'"}');

UPDATE H_INSTANCE hi
SET hi.SYS_EFF_END_DT=DATE_SUB(v_current_time, INTERVAL 1 MICROSECOND)
WHERE hi.LOCATIONID=NEW.LOCATIONID
AND   hi.RECORDDATE=NEW.RECORDDATE
AND   hi.RATEID=NEW.RATEID
AND   hi.sys_eff_end_dt=v_sys_eff_end_dt
AND   hi.AssetType=NEW.ASSETTYPE;

  INSERT INTO H_INSTANCE
      (  
             LOCATIONID
            ,RECORDDATE
            ,RATEID
            ,ASSETTYPE
            ,STATUSID
            ,RATEATTRJSON
            ,LOCKSTATUS
            ,DISTRIBUTIONCOUNT
            ,REASONCODEID
            ,COMMENTS
            ,OPS
            ,HOLIDAYFLAG
            ,WORKINGDAYFLAG
            ,T_1_DATE
            ,INTRAFLAG
            ,VIOLATIONID
            ,INSTANCEUPDATEDBY
            ,INSTANCEUPDATEDDATE
            ,CREATEDBY
            ,CREATEDDATE
            ,UPDATEDBY
            ,UPDATEDDATE
            ,SYS_EFF_BEG_DT
            ,SYS_EFF_END_DT
            ,DimChangeId
            ,AttrChangeId
            ,UsedInfo
            ,SessionInfo
            ,TriggerOrion
            ,Txid
            ,HasSubRates
            )
  VALUES (  
             NEW.LOCATIONID
                ,NEW.RECORDDATE
                ,NEW.RATEID
                ,NEW.ASSETTYPE
                ,NEW.STATUSID
                ,v_attr_json_str
                ,NEW.LOCKSTATUS
                ,NEW.DISTRIBUTIONCOUNT
                ,NEW.REASONCODEID
                ,NEW.COMMENTS
                ,NEW.OPS
                ,NEW.HOLIDAYFLAG
                ,NEW.WORKINGDAYFLAG
                ,NEW.T_1_DATE
                ,NEW.INTRAFLAG
                ,NEW.VIOLATIONID
                ,NEW.INSTANCEUPDATEDBY
                ,NEW.INSTANCEUPDATEDDATE
                ,NEW.CREATEDBY
                ,NEW.CREATEDDATE
                ,NEW.UPDATEDBY
                ,NEW.UPDATEDDATE
                ,v_current_time
                ,v_sys_eff_end_dt
                ,NEW.DimChangeId
               ,NEW.AttrChangeId
               ,NEW.UsedInfo
               ,Fn_UTIL_Get_SessionInfo()
               ,NEW.TriggerOrion
               ,NEW.Txid
               ,NEW.HasSubRates
       );
END
© www.soinside.com 2019 - 2024. All rights reserved.