JpaObjectRetrievalFailureException:找不到id为xxx的myapp.server.la



我需要你的帮助,因为我不明白发生了什么:我有一个异常是由一个永远不应该生成这个特定异常的代码引发的。我使用的是Spring Boot v2.2.7.RELEASE

例外情况是:

SERVER ERROR: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find myapp.server.layer3persistence.UserData with id 4673fa77-c8f2-45ac-886d-b5a8433044d6; nested exception is javax.persistence.EntityNotFoundException: Unable to find myapp.server.layer3persistence.UserData with id 4673fa77-c8f2-45ac-886d-b5a8433044d6] with root cause

堆栈跟踪为:

javax.persistence.EntityNotFoundException: Unable to find myapp.server.layer3persistence.UserData with id 9d8b7a7d-fd34-45d2-8a6a-68aee6ae1dd1
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:163)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:216)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:332)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:113)
at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1184)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1049)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:697)
at org.hibernate.type.EntityType.resolve(EntityType.java:464)
at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240)
at org.hibernate.engine.internal.TwoPhaseLoad$EntityResolver.lambda$static$0(TwoPhaseLoad.java:657)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntityEntryLoadedState(TwoPhaseLoad.java:252)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:184)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:153)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1203)
at org.hibernate.loader.Loader.processResultSet(Loader.java:1004)
at org.hibernate.loader.Loader.doQuery(Loader.java:962)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:352)
at org.hibernate.loader.Loader.doList(Loader.java:2857)
at org.hibernate.loader.Loader.doList(Loader.java:2839)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2671)
at org.hibernate.loader.Loader.list(Loader.java:2666)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:506)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:400)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:219)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1412)
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1565)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1533)
at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult(AbstractProducedQuery.java:1581)
at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getSingleResult(CriteriaQueryTypeQueryAdapter.java:111)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:196)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:618)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:149)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy106.findByProfileId(Unknown Source)
at myapp.server.layer2services.UserServices.addProfile(UserServices.java:332)
at myapp.server.layer1controllers.UserController.addSingleProfile(UserController.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

有趣的线路是:

at myapp.server.layer2services.UserServices.addProfile(UserServices.java:332)
at myapp.server.layer1controllers.UserController.addSingleProfile(UserController.java:68)

让我们试着看看有问题的线路:

用户控制器:66-69

@PostMapping("/addSingleProfile")
public void addSingleProfile(@RequestHeader String authToken, @RequestHeader String deviceId, @RequestBody String json) throws IOException {
userServices.addProfile(authToken, deviceId, json, true);
}

UserServices.java:326-346

public void addProfile(String authToken, String deviceId, String json, boolean isSingleProfile) throws IOException {
UserData userData = findUserByAuthTokenOrRequestLogout(authToken, deviceId);
UserProfile userProfile = new UserProfile(userData, new Gson().fromJson(json, UserProfileDAO.class));
// is it a new userProfile or an existing one to be updated?
if (userProfileRepository.existsByProfileId(userProfile.getProfileId())) {
UserProfile existingProfile = userProfileRepository.findByProfileId(userProfile.getProfileId()).get();
// the profile exists, so we update it
userProfile.setId(existingProfile.getId());
};
if (isSingleProfile) {
userData.getSingleProfiles().add(userProfile);
} else {
userData.getOrganizationProfiles().add(userProfile);
}
userProfileRepository.save(userProfile);
userDataRepository.save(userData);
}

java:332行(在堆栈跟踪中指示(是:

UserProfile existingProfile = userProfileRepository.findByProfileId(userProfile.getProfileId()).get();

但是这一行不能抛出给定的异常,因为它在if子句中:

if (userProfileRepository.existsByProfileId(userProfile.getProfileId())) {
UserProfile existingProfile = userProfileRepository.findByProfileId(userProfile.getProfileId()).get();
// the profile exists, so we update it
userProfile.setId(existingProfile.getId());
};

UserProfileDepository是这样实现的:

@Repository
@Transactional
public interface UserProfileRepository extends CrudRepository<UserProfile, String> {
public Optional<UserProfile> findByProfileId(String profileId);
public Optional<UserProfile> findByName(String name);
public Optional<UserProfile> findByNameIgnoreCase(String name);
public Optional<UserProfile> findByNameAndGroupKey(String name, String groupKey);
public boolean existsByProfileId(String profileId);
}

这个等价的代码也产生了同样的期望:

userProfileRepository.findByProfileId(userProfile.getProfileId()).ifPresent((UserProfile existingProfile) -> {
// the profile exists, so we update it
userProfile.setId(existingProfile.getId());
});

在我的案例中,类似的问题通过更新@ManyToOne注释得到了解决:

@NotNull
@JoinColumn(nullable = false)
@ManyToOne(optional = false, fetch = FetchType.LAZY)

添加:nullable = falseoptional = false, fetch = FetchType.LAZY加-@NotNull(javax.validation.constraints.NotNull(

最新更新