Springboot Jpa: [mysql] java.sql.SQLException: Duplicate entry ‘XXX‘ for key ‘PRIMARY‘

前言

1.问题背景

偶尔会出现登录请求出错的情况,一旦失败就会短时间内再也登录不上,更换浏览器或者刷新可能会暂时解决这个问题。

项目运行日志如下:

2022-07-21 09:43:40.946 DEBUG 8644 --- [http-nio-0.0.0.0-8080-exec-4] org.hibernate.SQL                        : select useraccoun0_.id as id1_65_, useraccoun0_.created_by_id as created23_65_, useraccoun0_.date_created as date_cre2_65_, useraccoun0_.is_valid as is_valid3_65_, useraccoun0_.last_update as last_upd4_65_, useraccoun0_.updated_by_id as updated24_65_, useraccoun0_.account_expired as account_5_65_, useraccoun0_.account_locked as account_6_65_, useraccoun0_.confirm_password as confirm_7_65_, useraccoun0_.department_id as departm25_65_, useraccoun0_.district as district8_65_, useraccoun0_.email as email9_65_, useraccoun0_.id_number as id_numb10_65_, useraccoun0_.id_type as id_type11_65_, useraccoun0_.image_url as image_u12_65_, useraccoun0_.is_admin as is_admi13_65_, useraccoun0_.name as name14_65_, useraccoun0_.need_approve as need_ap15_65_, useraccoun0_.open_id as open_id16_65_, useraccoun0_.password as passwor17_65_, useraccoun0_.password_expired as passwor18_65_, useraccoun0_.phone_number as phone_n19_65_, useraccoun0_.phone_reginal_number as phone_r20_65_, useraccoun0_.reference_user_id as referen26_65_, useraccoun0_.role_id as role_id27_65_, useraccoun0_.user_type as user_ty21_65_, useraccoun0_.username as usernam22_65_ from user_account useraccoun0_ where useraccoun0_.username=?
2022-07-21 09:43:40.947 DEBUG 8644 --- [http-nio-0.0.0.0-8080-exec-4] org.hibernate.SQL                        : select role0_.id as id1_56_0_, role0_.description as descript2_56_0_, role0_.is_valid as is_valid3_56_0_, role0_.name as name4_56_0_, role0_.role_name as role_nam5_56_0_, roleprivil1_.role_id as role_id1_57_1_, roleprivil2_.id as role_pri2_57_1_, roleprivil2_.id as id1_58_2_, roleprivil2_.privileges_id as privileg2_58_2_, roleprivil2_.role_id as role_id3_58_2_, privileges3_.id as id1_45_3_, privileges3_.parent_id as parent_i2_45_3_, privileges3_.privilege_code as privileg3_45_3_, privileges3_.privilege_name as privileg4_45_3_, privileges3_.privilege_path as privileg5_45_3_, privileges3_.privilege_type as privileg6_45_3_, role4_.id as id1_56_4_, role4_.description as descript2_56_4_, role4_.is_valid as is_valid3_56_4_, role4_.name as name4_56_4_, role4_.role_name as role_nam5_56_4_ from role role0_ left outer join role_role_privileges roleprivil1_ on role0_.id=roleprivil1_.role_id left outer join role_privileges roleprivil2_ on roleprivil1_.role_privileges_id=roleprivil2_.id left outer join privileges privileges3_ on roleprivil2_.privileges_id=privileges3_.id left outer join role role4_ on roleprivil2_.role_id=role4_.id where role0_.id=?
2022-07-21 09:43:40.951 DEBUG 8644 --- [http-nio-0.0.0.0-8080-exec-4] org.hibernate.SQL                        : select usertorole0_.user_account_id as user_acc1_66_0_, usertorole0_.user_to_roles_id as user_to_2_66_0_, usertorole1_.id as id1_68_1_, usertorole1_.role_id as role_id2_68_1_, usertorole1_.user_account_id as user_acc3_68_1_, role2_.id as id1_56_2_, role2_.description as descript2_56_2_, role2_.is_valid as is_valid3_56_2_, role2_.name as name4_56_2_, role2_.role_name as role_nam5_56_2_, useraccoun3_.id as id1_65_3_, useraccoun3_.created_by_id as created23_65_3_, useraccoun3_.date_created as date_cre2_65_3_, useraccoun3_.is_valid as is_valid3_65_3_, useraccoun3_.last_update as last_upd4_65_3_, useraccoun3_.updated_by_id as updated24_65_3_, useraccoun3_.account_expired as account_5_65_3_, useraccoun3_.account_locked as account_6_65_3_, useraccoun3_.confirm_password as confirm_7_65_3_, useraccoun3_.department_id as departm25_65_3_, useraccoun3_.district as district8_65_3_, useraccoun3_.email as email9_65_3_, useraccoun3_.id_number as id_numb10_65_3_, useraccoun3_.id_type as id_type11_65_3_, useraccoun3_.image_url as image_u12_65_3_, useraccoun3_.is_admin as is_admi13_65_3_, useraccoun3_.name as name14_65_3_, useraccoun3_.need_approve as need_ap15_65_3_, useraccoun3_.open_id as open_id16_65_3_, useraccoun3_.password as passwor17_65_3_, useraccoun3_.password_expired as passwor18_65_3_, useraccoun3_.phone_number as phone_n19_65_3_, useraccoun3_.phone_reginal_number as phone_r20_65_3_, useraccoun3_.reference_user_id as referen26_65_3_, useraccoun3_.role_id as role_id27_65_3_, useraccoun3_.user_type as user_ty21_65_3_, useraccoun3_.username as usernam22_65_3_, useraccoun4_.id as id1_65_4_, useraccoun4_.created_by_id as created23_65_4_, useraccoun4_.date_created as date_cre2_65_4_, useraccoun4_.is_valid as is_valid3_65_4_, useraccoun4_.last_update as last_upd4_65_4_, useraccoun4_.updated_by_id as updated24_65_4_, useraccoun4_.account_expired as account_5_65_4_, useraccoun4_.account_locked as account_6_65_4_, useraccoun4_.confirm_password as confirm_7_65_4_, useraccoun4_.department_id as departm25_65_4_, useraccoun4_.district as district8_65_4_, useraccoun4_.email as email9_65_4_, useraccoun4_.id_number as id_numb10_65_4_, useraccoun4_.id_type as id_type11_65_4_, useraccoun4_.image_url as image_u12_65_4_, useraccoun4_.is_admin as is_admi13_65_4_, useraccoun4_.name as name14_65_4_, useraccoun4_.need_approve as need_ap15_65_4_, useraccoun4_.open_id as open_id16_65_4_, useraccoun4_.password as passwor17_65_4_, useraccoun4_.password_expired as passwor18_65_4_, useraccoun4_.phone_number as phone_n19_65_4_, useraccoun4_.phone_reginal_number as phone_r20_65_4_, useraccoun4_.reference_user_id as referen26_65_4_, useraccoun4_.role_id as role_id27_65_4_, useraccoun4_.user_type as user_ty21_65_4_, useraccoun4_.username as usernam22_65_4_, useraccoun5_.id as id1_65_5_, useraccoun5_.created_by_id as created23_65_5_, useraccoun5_.date_created as date_cre2_65_5_, useraccoun5_.is_valid as is_valid3_65_5_, useraccoun5_.last_update as last_upd4_65_5_, useraccoun5_.updated_by_id as updated24_65_5_, useraccoun5_.account_expired as account_5_65_5_, useraccoun5_.account_locked as account_6_65_5_, useraccoun5_.confirm_password as confirm_7_65_5_, useraccoun5_.department_id as departm25_65_5_, useraccoun5_.district as district8_65_5_, useraccoun5_.email as email9_65_5_, useraccoun5_.id_number as id_numb10_65_5_, useraccoun5_.id_type as id_type11_65_5_, useraccoun5_.image_url as image_u12_65_5_, useraccoun5_.is_admin as is_admi13_65_5_, useraccoun5_.name as name14_65_5_, useraccoun5_.need_approve as need_ap15_65_5_, useraccoun5_.open_id as open_id16_65_5_, useraccoun5_.password as passwor17_65_5_, useraccoun5_.password_expired as passwor18_65_5_, useraccoun5_.phone_number as phone_n19_65_5_, useraccoun5_.phone_reginal_number as phone_r20_65_5_, useraccoun5_.reference_user_id as referen26_65_5_, useraccoun5_.role_id as role_id27_65_5_, useraccoun5_.user_type as user_ty21_65_5_, useraccoun5_.username as usernam22_65_5_, department6_.id as id1_11_6_, department6_.created_by_id as created_9_11_6_, department6_.date_created as date_cre2_11_6_, department6_.is_valid as is_valid3_11_6_, department6_.last_update as last_upd4_11_6_, department6_.updated_by_id as updated10_11_6_, department6_.description as descript5_11_6_, department6_.management_district as manageme6_11_6_, department6_.name as name7_11_6_, department6_.name_code as name_cod8_11_6_, useraccoun7_.id as id1_65_7_, useraccoun7_.created_by_id as created23_65_7_, useraccoun7_.date_created as date_cre2_65_7_, useraccoun7_.is_valid as is_valid3_65_7_, useraccoun7_.last_update as last_upd4_65_7_, useraccoun7_.updated_by_id as updated24_65_7_, useraccoun7_.account_expired as account_5_65_7_, useraccoun7_.account_locked as account_6_65_7_, useraccoun7_.confirm_password as confirm_7_65_7_, useraccoun7_.department_id as departm25_65_7_, useraccoun7_.district as district8_65_7_, useraccoun7_.email as email9_65_7_, useraccoun7_.id_number as id_numb10_65_7_, useraccoun7_.id_type as id_type11_65_7_, useraccoun7_.image_url as image_u12_65_7_, useraccoun7_.is_admin as is_admi13_65_7_, useraccoun7_.name as name14_65_7_, useraccoun7_.need_approve as need_ap15_65_7_, useraccoun7_.open_id as open_id16_65_7_, useraccoun7_.password as passwor17_65_7_, useraccoun7_.password_expired as passwor18_65_7_, useraccoun7_.phone_number as phone_n19_65_7_, useraccoun7_.phone_reginal_number as phone_r20_65_7_, useraccoun7_.reference_user_id as referen26_65_7_, useraccoun7_.role_id as role_id27_65_7_, useraccoun7_.user_type as user_ty21_65_7_, useraccoun7_.username as usernam22_65_7_, role8_.id as id1_56_8_, role8_.description as descript2_56_8_, role8_.is_valid as is_valid3_56_8_, role8_.name as name4_56_8_, role8_.role_name as role_nam5_56_8_ from user_account_user_to_roles usertorole0_ inner join user_to_role usertorole1_ on usertorole0_.user_to_roles_id=usertorole1_.id left outer join role role2_ on usertorole1_.role_id=role2_.id left outer join user_account useraccoun3_ on usertorole1_.user_account_id=useraccoun3_.id left outer join user_account useraccoun4_ on useraccoun3_.created_by_id=useraccoun4_.id left outer join user_account useraccoun5_ on useraccoun3_.updated_by_id=useraccoun5_.id left outer join department department6_ on useraccoun3_.department_id=department6_.id left outer join user_account useraccoun7_ on useraccoun3_.reference_user_id=useraccoun7_.id left outer join role role8_ on useraccoun3_.role_id=role8_.id where usertorole0_.user_account_id=?
2022-07-21 09:43:41.053 DEBUG 8644 --- [http-nio-0.0.0.0-8080-exec-4] org.hibernate.SQL                        : select * from role where id in (select role_id from user_to_role role where user_account_id = ?)
2022-07-21 09:43:41.058 DEBUG 8644 --- [http-nio-0.0.0.0-8080-exec-4] org.hibernate.SQL                        : insert into user_token (created_by_id, date_created, is_valid, last_update, updated_by_id, token, user_account_id, id) values (?, ?, ?, ?, ?, ?, ?, ?)
2022-07-21 09:43:41.066  WARN 8644 --- [http-nio-0.0.0.0-8080-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1062, SQLState: 23000
2022-07-21 09:43:41.066 ERROR 8644 --- [http-nio-0.0.0.0-8080-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper   : (conn=2673) Duplicate entry '1300' for key 'PRIMARY'
2022-07-21 09:43:41.067  INFO 8644 --- [http-nio-0.0.0.0-8080-exec-4] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements
2022-07-21 09:43:41.080 ERROR 8644 --- [http-nio-0.0.0.0-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause

java.sql.SQLException: Duplicate entry '1300' for key 'PRIMARY'
    at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readErrorPacket(AbstractQueryProtocol.java:1681) ~[mariadb-java-client-2.7.2.jar!/:na]
    at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readPacket(AbstractQueryProtocol.java:1543) ~[mariadb-java-client-2.7.2.jar!/:na]
    at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.getResult(AbstractQueryProtocol.java:1506) ~[mariadb-java-client-2.7.2.jar!/:na]
    at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.executeQuery(AbstractQueryProtocol.java:316) ~[mariadb-java-client-2.7.2.jar!/:na]
    at org.mariadb.jdbc.ClientSidePreparedStatement.executeInternal(ClientSidePreparedStatement.java:220) ~[mariadb-java-client-2.7.2.jar!/:na]
    at org.mariadb.jdbc.ClientSidePreparedStatement.execute(ClientSidePreparedStatement.java:149) ~[mariadb-java-client-2.7.2.jar!/:na]
    at org.mariadb.jdbc.ClientSidePreparedStatement.executeUpdate(ClientSidePreparedStatement.java:181) ~[mariadb-java-client-2.7.2.jar!/:na]
    at jdk.internal.reflect.GeneratedMethodAccessor374.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:114) ~[tomcat-jdbc-9.0.44.jar!/:na]
    at jdk.proxy2/jdk.proxy2.$Proxy130.executeUpdate(Unknown Source) ~[na:na]
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:46) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3375) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3908) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:107) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:344) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1407) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:489) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3290) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2425) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:449) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.6.9.Final.jar!/:5.6.9.Final]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562) ~[spring-orm-5.3.5.jar!/:5.3.5]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743) ~[spring-tx-5.3.5.jar!/:5.3.5]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) ~[spring-tx-5.3.5.jar!/:5.3.5]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654) ~[spring-tx-5.3.5.jar!/:5.3.5]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407) ~[spring-tx-5.3.5.jar!/:5.3.5]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.5.jar!/:5.3.5]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.5.jar!/:5.3.5]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.5.jar!/:5.3.5]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.5.jar!/:5.3.5]
    at com.beyondsoft.sabg.testlab.service.core.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$fc6510b4.login(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
    at com.beyondsoft.sabg.testlab.controller.user.LoginAndLogoutController.login(LoginAndLogoutController.java:88) ~[classes!/:0.0.1-SNAPSHOT]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.5.jar!/:5.3.5]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.5.jar!/:5.3.5]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.5.jar!/:5.3.5]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.5.jar!/:5.3.5]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.5.jar!/:5.3.5]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.5.jar!/:5.3.5]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.5.jar!/:5.3.5]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.5.jar!/:5.3.5]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.44.jar!/:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.5.jar!/:5.3.5]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.44.jar!/:4.0.FR]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:149) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at com.beyondsoft.sabg.testlab.security.jwt.JwtTokenFilter.doFilter(JwtTokenFilter.java:45) ~[classes!/:0.0.1-SNAPSHOT]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.4.5.jar!/:5.4.5]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.5.jar!/:5.3.5]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.44.jar!/:9.0.44]
    at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

查看运行日志看出,报错原因: java.sql.SQLException: Duplicate entry '1300' for key 'PRIMARY'

因为重复的主键而报错,头大!!!

仔细的查看代码和数据库数据,确定是因为保存token时主键重复。

代码如下:

@Override
    @Transactional
    public List<Map<String, Object>> login(String username, String password) {

        Map<String, Object> userInfoMap = new HashMap<>();
        List<Map<String, Object>> userInfo = new ArrayList<Map<String, Object>>();

        try {
            Authentication auth = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(username, password));
            UserAccount account = (UserAccount) auth.getPrincipal();
            Map<String, Object> accountMap = getUserPublicInfo(account);
            userInfo.add(accountMap);
            String token = jwtTokenProvider.createToken(username);

            UserToken t = new UserToken();
            t.setToken(token);
            t.setUserAccount(account);

            userInfoMap.put("token", token);
            userInfo.add(userInfoMap);
            tokenRepository.save(t);
            return userInfo;
        } catch (AuthenticationException e) {
            userInfoMap.put("error", "账号登陆错误!");
            userInfo.add(userInfoMap);
            log.debug("Authentication error: %s", username);
        }

        return null;
    }

public class UserToken extends AbstractEntity {

    String token;

    @ManyToOne
    UserAccount userAccount;

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public UserAccount getUserAccount() {
        return userAccount;
    }

    public void setUserAccount(UserAccount userAccount) {
        this.userAccount = userAccount;
    }
}

2.解决问题:

2.1.引起数据重复的原因有哪些

表象原因:如网络延迟、用户连点、并发等,都有可能引起数据库被重复插入。

可能原因:如主键没有设置自增、插入线程频率过高,没有处置好事务,造成插入SQL执行顺序混乱等。  

2.2.解决思路

首先问题产生是因为有重复主键,谁产生的这个问题,是在登录接口中调用保存token时产生。

解决1:

设置主键自增

然而本身我们就设置了主键自增,所以并不是这个问题引起的。

猜想:是不是save哪里有问题

save使用的是springboot JPA中的save()方法,查看JPA的save方法的实现。

JPA 的 save 默认会判断是否为新数据,若为新数据则 insert / persist,否则 update / merge。

具体实现是先select后insert/update,查询没有该数据就插入数据,有则更新。

jpa save方法源码:

@Transactional
    @Override
    public <S extends T> S save(S entity) {

        Assert.notNull(entity, "Entity must not be null.");

        if (entityInformation.isNew(entity)) {
            em.persist(entity);
            return entity;
        } else {
            return em.merge(entity);
        }
    }

save方法运行sql

org.hibernate.SQL                        : select max(id) from user_token
org.hibernate.SQL                        : insert into user_token (created_by_id, date_created, is_valid, last_update, updated_by_id, token, user_account_id, id) values (?, ?, ?, ?, ?, ?, ?, ?)

 "select max(id) from user_token" 获取最大id号,因为是主键设置的是自增,最大id号将作为新插入数据的主键id。

从这个思路出发,我们使用的是mysql数据库,本身我们数据库插入表的主键id是自增的,作为数据库主键而言,唯一性已经不能保证不会出现插入表数据有多个锁的情况,所以报错重复的主键冲突,会不会是因为jpa在保存时先find后再save,在这个过程db报错。

解决2:

在实体类中实现 Persistable interface 的 isNew method,固定返回 true,则在 JPA save 时一定会执行 insert sql,代码如下:

@Entity
public class UserToken extends AbstractEntity implements Persistable{

    String token;

    @ManyToOne
    UserAccount userAccount;

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public UserAccount getUserAccount() {
        return userAccount;
    }

    public void setUserAccount(UserAccount userAccount) {
        this.userAccount = userAccount;
    }

    @Override
    public boolean isNew() {
        return true;
    }
}

上面这种方式除外,还可以不对实体做改变,直接 Repository 自定义 Query。

然而并没有解决我的问题。

猜测:会不会不仅只是这个save引起的,可能还有别的原因

从这个思路重新出发,查看代码,发现在UserToken实体对用户有关联关系,那会不会是因为对于一个关联的外键表存在一个唯一的约束,然而你又对这个唯一的约束新增一个同样的字段。所以我去查看了一下新增的这个关系表对应的外键是否存在,结果存在,查看JPA一对多的关系是否选择是同时合并,和同时持久化操作,结果没有,从这点可以试试是不是这个原因引起的。补充:如果是同时持久化操作就会在更新外键表的时候自己修改主表,主表根据ID修改,如果没有ID就会新增一个主表数据。

ALL
级联所有实体状态转换

PERSIST
级联实体持久化操作

MERGE
级联实体合并操作

REMOVE
级联实体删除操作

REFRESH
级联实体刷新操作

DETACH
级联实体分离操作

@Cascade(value = CascadeType.ALL) 
@ManyToOne(fetch = FetchType.EAGER)

UserAccount userAccount;

(@OneToMany(cascade = {CascadeType.ALL} ,fetch= FetchType.EAGER))

  到此我的问题解决!!!如果你的问题还未解决,可以考虑除去save之外的原因,比如:业务上是否有问题等。

从头梳理一下,发现还是有问题,需要注意的是CascadeType.ALL尽量不要乱用,all在所有情况下均进行关联操作,即save-update和delete,做删除操作时会导致关联实体删除,如果你的需求不需要关联删除就不能使用all。

最终方案是:

@Cascade(value = CascadeType.SAVE_UPDATE)
@ManyToOne(fetch = FetchType.EAGER)

UserAccount userAccount;

补充:cascade属性的可能值有

all: 所有情况下均进行关联操作,即save-update和delete。

none: 所有情况下均不进行关联操作。这是默认值。

save-update: 在执行save/update/saveOrUpdate时进行关联操作,例如:当保存A,同时保存关联对象B,不需要手动执行save(B)。

delete: 在执行delete 时进行关联操作,例如:当删除A时,同时删除关联对象B。

merge:merge方法产生的效果来看,它和saveOrUpdate()方法相似,根据参数有无id或id是否已经存在来理解merge()方法。个人认为这样更容易理解,而且从执行他们两个方法而产生的sql语句来看是一样的。

all-delete-orphan: 所有级联操作,当一个节点在对象图中成为孤儿节点时,删除该节点。

hibernate 3已经将cascade当中的选项做了修改,现在已经没有了all-delete-orphan这个选项,虽然hibernate内部还是支持这个选项。

如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值