Spring Boot中@LastModifiedBy用User类型触发StackOverflowError问题
问题背景
最初在Spring Boot应用中,Book实体类的@LastModifiedBy字段为String类型时,JPA审计功能正常工作,相关代码如下:
Book实体类
@Entity @EntityListeners(AuditingEntityListener.class) public class Book { @Id private Long id; private String title; @LastModifiedDate private LocalDateTime lastModified; @LastModifiedBy private String lastModifiedBy; }
JpaAuditingConfig配置类
@Configuration @EnableJpaAuditing(auditorAwareRef = "auditorProvider") public class JpaAuditingConfig { private final AuthService authService; public JpaAuditingConfig(AuthService authService) { this.authService= authService; } @Bean public AuditorAware<String> auditorProvider() { return () -> Optional.ofNullable(authService.getUsername()); } }
AuthService类
@Service public class AuthService { private final UserService userService; public String getUsername() { return SecurityContextHolder.getContext().getAuthentication().getPrincipal(); } public User getUser() { return this.userService.getByUsername(this.getUsername()); } }
当将@LastModifiedBy字段改为User类型,并修改auditorProvider返回AuditorAware<User>后,保存Book实体时出现StackOverflowError,报错信息如下:
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at s\src\java.instrument\share\native\libinstrument\JPLISAgent.c line: 884 org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction Caused by: jakarta.persistence.RollbackException: Error while committing the transaction at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:67) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104) at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:561) ... 115 more Caused by: java.lang.RuntimeException: java.lang.StackOverflowError
栈溢出原因分析
核心原因是实体双向关联引发的无限递归加载:
- 当
@LastModifiedBy改为User类型后,Book与User形成了关联关系,若User实体中同时存在关联Book的集合字段(比如List<Book> books),就构成了双向关联。 - 事务提交时,Hibernate会对持久化上下文做脏检查:遍历User对象时会加载其关联的Book集合,遍历Book对象时又会加载其关联的User实例,如此循环往复,调用栈不断加深,最终触发StackOverflowError。
- 另一种可能是
AuthService.getUser()获取User实例时,触发了额外的级联操作或循环依赖,但最常见的诱因还是双向关联未做递归阻断处理。
内容的提问来源于stack exchange,提问作者Kamil
相关产品推荐
相关产品推荐

