spring jpa在更新实体期间的流异常,它具有实体监听器

时间:2018-01-02 06:45:45

标签: spring jpa

我正在开发一个Spring boot 1.5.9.release和data-jpa 1.5.9.RELEASE的项目,我的项目中有一些实体,一个实体有@CreatedBy注释注入spring security authentication.getPrincipal()对象在插入或更新期间。它通过使用@EntityListener注释自动生成。

插入新行时一切都很好但是,当我更新我的持久化实体时,它会引发很多错误 - 大多数错误都会反复出现。

我的代码如下:

配置文件的一部分。

@EnableJpaAuditing(dateTimeProviderRef="dateTimeProvider")
@Configuration
public class CoreConfig {

    @Bean
    public AuditorAware<Member> auditorAware(){
        return new AuditorAwareImpl();
    }

    @Bean
    public DateTimeProvider dateTimeProvider(){
        return new DateTimeProviderImpl();
    }
}

AuditorAwareImpl

public class AuditorAwareImpl implements AuditorAware<Member>{

    private static Logger logger = LoggerFactory.getLogger(AuditorAwareImpl.class);

    @Autowired
    private MemberService memberService;

    @Override
    public Member getCurrentAuditor() {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if(authentication == null){
            return null;
        }

        String userEmail = authentication.getPrincipal().toString();
        logger.info("JPA Audit username: [{}]", userEmail);

        return memberService.findByEmail(userEmail);
    }

}

导致错误堆栈的服务层。

@Transactional
@Service
public class GalleryReplyServiceImpl implements GalleryReplyService{

    // .. skipped   

    @Override
    public void editReply(GalleryReplyVO vo) {
        GalleryReply reply = repository.findOne(Long.parseLong(vo.getReplySeq()));
        reply.setMessage(vo.getMessage()); // this line is problematic.
    }



}

用户权利:

@Entity
@Table(name="MEMBER", uniqueConstraints={
        @UniqueConstraint(columnNames={"USER_SEQ"}),
        @UniqueConstraint(columnNames={"USER_EMAIL"}),
        @UniqueConstraint(columnNames={"NICKNAME"})
})
@Data
@NoArgsConstructor
@RequiredArgsConstructor(staticName="of")
public class Member implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="USER_SEQ", unique=true, nullable=false)
    private Long userSeq; 

    @Email
    @NotEmpty(message="이메일을 입력해주세요.")
    @NonNull
    @Column(name="USER_EMAIL", unique=true, nullable=false, length=50)
    private String userEmail;

    @NotEmpty(message="비밀번호를 입력해주세요.")
    @NonNull
    @Column(name="USER_PW", nullable=false, length=255)
    private String userPw;

    @Size(min=2, max=10)
    @NonNull
    @Column(name="NICKNAME", unique=true, nullable=false, length=20)
    private String nickname;

    @OneToOne(mappedBy="member", cascade=CascadeType.ALL)
    private MemberSecurity security;

    @Override
    public String toString() {
        return "Member [userSeq=" + userSeq + ", userEmail=" + userEmail + ", userPw=" + userPw + ", nickname="
                + nickname + "]";
    }

    // skipped...

}

以逻辑方式播放的实体(更新此实体会触发错误堆栈)。

@EntityListeners(AuditingEntityListener.class)
@Entity
@Table(name="GALLERY_REPLY", uniqueConstraints={
        @UniqueConstraint(columnNames="REPLY_SEQ")
})
@Data
@NoArgsConstructor
@RequiredArgsConstructor(staticName="of")
public class GalleryReply implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="REPLY_SEQ", nullable=false, unique=true)
    private Long replySeq;

    @ManyToOne
    @JoinColumn(name="GALLERY_SEQ", referencedColumnName="GALLERY_SEQ")
    private Gallery gallery;

    @ManyToOne
    @JoinColumn(name="USER_SEQ", referencedColumnName="USER_SEQ")
    @CreatedBy
    private Member member;

    @NonNull
    @Lob
    @Column(name="MSG", nullable=false)
    private String message;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="CREATED_DT", nullable=false)
    @CreatedDate
    private Date createdDate;

    @ManyToOne
    @JoinColumn(name="REPLY_AT", referencedColumnName="REPLY_SEQ")
    private GalleryReply replyAt;

    @OneToMany(mappedBy="replyAt")
    private Set<GalleryReply> subordinateds;

    @Override
    public String toString() {
        return "GalleryReply [replySeq=" + replySeq + ", message=" + message + ", createdDate=" + createdDate + "]";
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        GalleryReply other = (GalleryReply) obj;
        if (replySeq == null) {
            if (other.replySeq != null)
                return false;
        } else if (!replySeq.equals(other.replySeq))
            return false;
        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((replySeq == null) ? 0 : replySeq.hashCode());
        return result;
    }



}

错误堆栈是:

2018-01-02 15:31:24 [http-nio-8080-exec-7] INFO  c.m.c.core.util.AuditorAwareImpl - JPA Audit username: [musicovery12@naver.com]
2018-01-02 15:31:24 [http-nio-8080-exec-7] INFO  c.m.c.core.util.AuditorAwareImpl - JPA Audit username: [musicovery12@naver.com]
2018-01-02 15:31:24 [http-nio-8080-exec-7] INFO  c.m.c.core.util.AuditorAwareImpl - JPA Audit username: [musicovery12@naver.com]
2018-01-02 15:31:24 [http-nio-8080-exec-7] INFO  c.m.c.core.util.AuditorAwareImpl - JPA Audit username: [musicovery12@naver.com]
2018-01-02 15:31:24 [http-nio-8080-exec-7] INFO  c.m.c.core.util.AuditorAwareImpl - JPA Audit username: [musicovery12@naver.com]
2018-01-02 15:31:24 [http-nio-8080-exec-7] INFO  c.m.c.core.util.AuditorAwareImpl - JPA Audit username: [musicovery12@naver.com]
2018-01-02 15:31:24 [http-nio-8080-exec-7] INFO  c.m.c.core.util.AuditorAwareImpl - JPA Audit username: [musicovery12@naver.com]
2018-01-02 15:31:24 [http-nio-8080-exec-7] INFO  c.m.c.core.util.AuditorAwareImpl - JPA Audit username: [musicovery12@naver.com]
2018-01-02 15:31:24 [http-nio-8080-exec-7] INFO  c.m.c.core.util.AuditorAwareImpl - JPA Audit username: [musicovery12@naver.com]
2018-01-02 15:31:24 [http-nio-8080-exec-7] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [/cookingstep2] threw exception [Request processing failed; nested exception is org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction] with root cause
java.lang.StackOverflowError: null
    at org.hibernate.jpa.criteria.path.RootImpl.render(RootImpl.java:85)
    at org.hibernate.jpa.criteria.path.RootImpl.renderProjection(RootImpl.java:91)
    at org.hibernate.jpa.criteria.QueryStructure.render(QueryStructure.java:239)
    at org.hibernate.jpa.criteria.CriteriaQueryImpl.interpret(CriteriaQueryImpl.java:292)
    at org.hibernate.jpa.criteria.compile.CriteriaCompiler.compile(CriteriaCompiler.java:130)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:699)
    at sun.reflect.GeneratedMethodAccessor103.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347)
    at com.sun.proxy.$Proxy123.createQuery(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor103.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298)
    at com.sun.proxy.$Proxy123.createQuery(Unknown Source)
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:205)
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:155)
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.doCreateQuery(PartTreeJpaQuery.java:86)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.createQuery(AbstractJpaQuery.java:190)
    at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:208)
    at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:87)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:116)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:106)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:499)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:477)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:115)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy132.findByUserEmail(Unknown Source)
    at com.musicovery12.cookingstep2.core.service.MemberServiceImpl.findByEmail(MemberServiceImpl.java:61)
    at com.musicovery12.cookingstep2.core.service.MemberServiceImpl$$FastClassBySpringCGLIB$$3b245c15.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
    at com.musicovery12.cookingstep2.core.service.MemberServiceImpl$$EnhancerBySpringCGLIB$$b2806f0.findByEmail(<generated>)
    at com.musicovery12.cookingstep2.core.util.AuditorAwareImpl.getCurrentAuditor(AuditorAwareImpl.java:32)
    at com.musicovery12.cookingstep2.core.util.AuditorAwareImpl.getCurrentAuditor(AuditorAwareImpl.java:1)
    at org.springframework.data.auditing.AuditingHandler.touchAuditor(AuditingHandler.java:176)
    at org.springframework.data.auditing.AuditingHandler.touch(AuditingHandler.java:155)
    at org.springframework.data.auditing.AuditingHandler.markModified(AuditingHandler.java:134)
    at org.springframework.data.jpa.domain.support.AuditingEntityListener.touchForUpdate(AuditingEntityListener.java:96)
    at sun.reflect.GeneratedMethodAccessor104.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.hibernate.jpa.event.internal.jpa.ListenerCallback.performCallback(ListenerCallback.java:35)
    at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:94)
    at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.preUpdate(CallbackRegistryImpl.java:68)
    at org.hibernate.jpa.event.internal.core.JpaFlushEntityEventListener.invokeInterceptor(JpaFlushEntityEventListener.java:51)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.handleInterception(DefaultFlushEntityEventListener.java:325)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:276)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:143)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44)
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1251)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1319)
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87)
    at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:606)
    at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:529)
    at org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getSingleResult(CriteriaQueryTypeQueryAdapter.java:54)
    at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:208)
    at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:87)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:116)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:106)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:499)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:477)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:115)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy132.findByUserEmail(Unknown Source)
    at com.musicovery12.cookingstep2.core.service.MemberServiceImpl.findByEmail(MemberServiceImpl.java:61)
    at com.musicovery12.cookingstep2.core.service.MemberServiceImpl$$FastClassBySpringCGLIB$$3b245c15.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
    at com.musicovery12.cookingstep2.core.service.MemberServiceImpl$$EnhancerBySpringCGLIB$$b2806f0.findByEmail(<generated>)
    at com.musicovery12.cookingstep2.core.util.AuditorAwareImpl.getCurrentAuditor(AuditorAwareImpl.java:32)
    at com.musicovery12.cookingstep2.core.util.AuditorAwareImpl.getCurrentAuditor(AuditorAwareImpl.java:1)
    at org.springframework.data.auditing.AuditingHandler.touchAuditor(AuditingHandler.java:176)
    at org.springframework.data.auditing.AuditingHandler.touch(AuditingHandler.java:155)
    at org.springframework.data.auditing.AuditingHandler.markModified(AuditingHandler.java:134)
    at org.springframework.data.jpa.domain.support.AuditingEntityListener.touchForUpdate(AuditingEntityListener.java:96)
    at sun.reflect.GeneratedMethodAccessor104.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.hibernate.jpa.event.internal.jpa.ListenerCallback.performCallback(ListenerCallback.java:35)
    at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:94)
    at org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl.preUpdate(CallbackRegistryImpl.java:68)
    at org.hibernate.jpa.event.internal.core.JpaFlushEntityEventListener.invokeInterceptor(JpaFlushEntityEventListener.java:51)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.handleInterception(DefaultFlushEntityEventListener.java:325)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:276)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:143)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44)
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1251)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1319)
... over and over and ends by some time.

我认为这是实体的双向原因。有什么帮助吗?

0 个答案:

没有答案