這個問題很好描述在老春天論壇主題this中。當嘗試用@CreatedBy更新任何實體時java.lang.StackOverflowError
現在我堅持着同樣的問題。當我嘗試使用網絡請求中的@CreatedBy Employee employee
字段更新任何實體時,將發生exception。
前100行的堆棧跟蹤日誌:
2016-01-12 22:14:02.941 ERROR 8720 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: java.lang.StackOverflowError] with root cause
java.lang.StackOverflowError: null
at java.util.Collections$SynchronizedMap.get(Unknown Source) ~[na:1.8.0_66]
at org.springframework.data.util.ClassTypeInformation.from(ClassTypeInformation.java:74) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.mapping.context.AbstractMappingContext.hasPersistentEntityFor(AbstractMappingContext.java:148) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.mapping.context.PersistentEntities.getPersistentEntity(PersistentEntities.java:62) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory.getBeanWrapperFor(MappingAuditableBeanWrapperFactory.java:76) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.auditing.AuditingHandler.touch(AuditingHandler.java:139) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.auditing.AuditingHandler.markModified(AuditingHandler.java:134) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.jpa.domain.support.AuditingEntityListener.touchForUpdate(AuditingEntityListener.java:96) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at sun.reflect.GeneratedMethodAccessor147.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_66]
at org.hibernate.jpa.event.internal.jpa.ListenerCallback.performCallback(ListenerCallback.java:32) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:95) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.preUpdate(CallbackRegistryImpl.java:59) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.event.internal.core.JpaFlushEntityEventListener.invokeInterceptor(JpaFlushEntityEventListener.java:51) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.DefaultFlushEntityEventListener.handleInterception(DefaultFlushEntityEventListener.java:325) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:276) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:143) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1193) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1261) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:567) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:482) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getSingleResult(CriteriaQueryTypeQueryAdapter.java:54) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:206) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:78) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:100) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:91) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:454) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:432) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:101) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at com.sun.proxy.$Proxy474.findByLogin(Unknown Source) ~[na:na]
at point.office.CurrentUserImpl.get(CurrentUserImpl.java:42) ~[bin/:na]
at sun.reflect.GeneratedMethodAccessor290.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_66]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at com.sun.proxy.$Proxy480.get(Unknown Source) ~[na:na]
at point.office.SpringSecurityAuditorAware.getCurrentAuditor(SpringSecurityAuditorAware.java:21) ~[bin/:na]
at point.office.SpringSecurityAuditorAware.getCurrentAuditor(SpringSecurityAuditorAware.java:1) ~[bin/:na]
at org.springframework.data.auditing.AuditingHandler.touchAuditor(AuditingHandler.java:166) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.auditing.AuditingHandler.touch(AuditingHandler.java:145) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.auditing.AuditingHandler.markModified(AuditingHandler.java:134) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.jpa.domain.support.AuditingEntityListener.touchForUpdate(AuditingEntityListener.java:96) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at sun.reflect.GeneratedMethodAccessor147.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_66]
at org.hibernate.jpa.event.internal.jpa.ListenerCallback.performCallback(ListenerCallback.java:32) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:95) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.preUpdate(CallbackRegistryImpl.java:59) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.event.internal.core.JpaFlushEntityEventListener.invokeInterceptor(JpaFlushEntityEventListener.java:51) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.DefaultFlushEntityEventListener.handleInterception(DefaultFlushEntityEventListener.java:325) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:276) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:143) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1193) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1261) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87) ~[hibernate-core-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:567) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:482) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getSingleResult(CriteriaQueryTypeQueryAdapter.java:54) ~[hibernate-entitymanager-5.0.3.Final.jar:5.0.3.Final]
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:206) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:78) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:100) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:91) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:454) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:432) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61) ~[spring-data-commons-1.11.0.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:101) ~[spring-data-jpa-1.9.0.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at com.sun.proxy.$Proxy474.findByLogin(Unknown Source) ~[na:na]
at point.office.CurrentUserImpl.get(CurrentUserImpl.java:42) ~[bin/:na]
我AuditorAware
實現:
@Component
public class SpringSecurityAuditorAware implements AuditorAware<Employee> {
private final CurrentUser currentUser;
@Autowired
public SpringSecurityAuditorAware(CurrentUser currentUser) {
this.currentUser = currentUser;
}
@Override
public Employee getCurrentAuditor() {
return currentUser.get();
}
}
而且我CurrentUser
服務實現:
@Service
public class CurrentUserImpl implements CurrentUser {
private final EmployeeRepository employeeRepository;
@Autowired
public CurrentUserImpl(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
@Override
public Employee get() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return null;
}
return employeeRepository.findByLogin(authentication.getName()).orElseGet(() -> null);
}
}
而且我EmployeeRepository
是:
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
Optional<Employee> findByLogin(String login);
}
我試圖在異常發生時更新的實體可以是任何實體,其字段由spring的@CreatedBy
註釋。例如:
@Entity
@NoArgsConstructor
@Getter @Setter
public class Issue extends AbstractPersistable<Integer> {
@CreatedDate
@Column(nullable = false)
private LocalDateTime createdAt;
@CreatedBy
@ManyToOne(optional = false)
private Employee createdBy;
@Column(nullable = true)
private String body;
}
如果這個實體,我會做的事:
Issue issue = issueRepository.findOne(1);
issue.setBody("new issue body");
issueRepository.saveAndFlush(issue);
然後發生異常。
我發現了一個解決方法:如果我將@Transactional(propagation = Propagation.REQUIRES_NEW)
添加到我的Employee get()
方法,那麼所有開始工作。但是爲什麼沒有它就無法工作?也許春季數據有bug?或者我做錯了什麼?
你什麼異常?請在您的帖子中包含所有相關信息,而不是在外部網站上。 – dunni
我向外部網站發佈了異常,因爲'stackoverflow.com'說我的消息太大。我認爲他只是嫉妒,因爲我的例外是'java.lang.StackOverflowError'。 :) – djxak
是的,你不應該盲目地發佈任何東西,而是將其去掉相關的行。對於StackOverflowException,通常前30到50行就足夠了。 – dunni