Stackoverflow на @PreUpdate

Я получаю исключение stackoverflow, когда я пытаюсь использовать аннотацию @PreUpdate для объекта, который использует Embedded Auditable Entity и @EntityListeners.

В моем объекте я пытаюсь получить данные пользователя через службу, чтобы обновить поля CreateBy / LastUpdateBy на моем объекте. Я не могу просто поместить в него String, мне нужна ссылка на самого User.

Я уже пробовал подход с внедрением диспетчера сущностей в AuditListener и его очисткой вручную, но он не работает должным образом. Кроме того, я попытался передать данные пользователя в контексте Spring вместо использования службы, но, поскольку он сохраняет статические значения, мне это не нужно. Мне нужно как-то получить объект User внутри AuditListener, не заходя в бесконечный цикл.

Любые идеи?

Вот stacktrace:

2019-01-04 15:45:52 ERROR 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.lang.ClassLoader.defineClass1(Native Method)
                at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
                at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
                at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
                at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
                at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
                at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
                at java.security.AccessController.doPrivileged(Native Method)
                at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
                at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
                at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
                at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
                at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
                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.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)
                at com.app.server.repositories.impl.UserRepositoryImpl$$EnhancerBySpringCGLIB$$d072e6d0.findByUsername(<generated>)
                at com.app.server.services.impl.UserServiceImpl.findUserByUsername(UserServiceImpl.java:131)
                at com.app.server.services.impl.UserServiceImpl$$FastClassBySpringCGLIB$$852b5ce2.invoke(<generated>)
                at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
                at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:667)
                at com.app.server.services.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$80381f41.findUserByUsername(<generated>)
                at com.app.server.defautmodel.audit.UserTimeAuditListener.setUpdatedOn(UserTimeAuditListener.java:37)
                at sun.reflect.GeneratedMethodAccessor177.invoke(Unknown Source)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.lang.reflect.Method.invoke(Method.java:498)
                at org.hibernate.jpa.event.internal.ListenerCallback.performCallback(ListenerCallback.java:35)
                at org.hibernate.jpa.event.internal.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:97)
                at org.hibernate.jpa.event.internal.CallbackRegistryImpl.preUpdate(CallbackRegistryImpl.java:71)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.invokeInterceptor(DefaultFlushEntityEventListener.java:350)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.handleInterception(DefaultFlushEntityEventListener.java:332)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:283)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:154)
                at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:235)
                at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:94)
                at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44)
                at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1415)
                at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1501)
                at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1537)
                at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1505)
                at org.hibernate.query.Query.getResultList(Query.java:135)
                at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:74)
                at com.app.server.repositories.impl.UserRepositoryImpl.findByUsername(UserRepositoryImpl.java:40)
                at com.app.server.repositories.impl.UserRepositoryImpl$$FastClassBySpringCGLIB$$46c3b507.invoke(<generated>)
                at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
                at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
                at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
                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.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)
                at com.app.server.repositories.impl.UserRepositoryImpl$$EnhancerBySpringCGLIB$$d072e6d0.findByUsername(<generated>)
                at com.app.server.services.impl.UserServiceImpl.findUserByUsername(UserServiceImpl.java:131)
                at com.app.server.services.impl.UserServiceImpl$$FastClassBySpringCGLIB$$852b5ce2.invoke(<generated>)
                at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
                at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:667)
                at com.app.server.services.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$80381f41.findUserByUsername(<generated>)
                at com.app.server.defautmodel.audit.UserTimeAuditListener.setUpdatedOn(UserTimeAuditListener.java:37)
                at sun.reflect.GeneratedMethodAccessor177.invoke(Unknown Source)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.lang.reflect.Method.invoke(Method.java:498)
                at org.hibernate.jpa.event.internal.ListenerCallback.performCallback(ListenerCallback.java:35)
                at org.hibernate.jpa.event.internal.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:97)
                at org.hibernate.jpa.event.internal.CallbackRegistryImpl.preUpdate(CallbackRegistryImpl.java:71)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.invokeInterceptor(DefaultFlushEntityEventListener.java:350)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.handleInterception(DefaultFlushEntityEventListener.java:332)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:283)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:154)
                at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:235)
                at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:94)
                at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44)
                at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1415)
                at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1501)
                at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1537)
                at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1505)
                at org.hibernate.query.Query.getResultList(Query.java:135)
                at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:74)
                at com.app.server.repositories.impl.UserRepositoryImpl.findByUsername(UserRepositoryImpl.java:40)
                at com.app.server.repositories.impl.UserRepositoryImpl$$FastClassBySpringCGLIB$$46c3b507.invoke(<generated>)
                at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
                at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
                at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
                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.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)
                at com.app.server.repositories.impl.UserRepositoryImpl$$EnhancerBySpringCGLIB$$d072e6d0.findByUsername(<generated>)
                at com.app.server.services.impl.UserServiceImpl.findUserByUsername(UserServiceImpl.java:131)
                at com.app.server.services.impl.UserServiceImpl$$FastClassBySpringCGLIB$$852b5ce2.invoke(<generated>)
                at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
                at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:667)
                at com.app.server.services.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$80381f41.findUserByUsername(<generated>)
                at com.app.server.defautmodel.audit.UserTimeAuditListener.setUpdatedOn(UserTimeAuditListener.java:37)
                at sun.reflect.GeneratedMethodAccessor177.invoke(Unknown Source)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.lang.reflect.Method.invoke(Method.java:498)
                at org.hibernate.jpa.event.internal.ListenerCallback.performCallback(ListenerCallback.java:35)
                at org.hibernate.jpa.event.internal.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:97)
                at org.hibernate.jpa.event.internal.CallbackRegistryImpl.preUpdate(CallbackRegistryImpl.java:71)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.invokeInterceptor(DefaultFlushEntityEventListener.java:350)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.handleInterception(DefaultFlushEntityEventListener.java:332)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:283)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:154)
                at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:235)
                at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:94)
                at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44)
                at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1415)
                at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1501)
                at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1537)
                at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1505)
                at org.hibernate.query.Query.getResultList(Query.java:135)
                at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:74)
                at com.app.server.repositories.impl.UserRepositoryImpl.findByUsername(UserRepositoryImpl.java:40)
                at com.app.server.repositories.impl.UserRepositoryImpl$$FastClassBySpringCGLIB$$46c3b507.invoke(<generated>)
                at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
                at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
                at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
                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.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)
                at com.app.server.repositories.impl.UserRepositoryImpl$$EnhancerBySpringCGLIB$$d072e6d0.findByUsername(<generated>)
                at com.app.server.services.impl.UserServiceImpl.findUserByUsername(UserServiceImpl.java:131)
                at com.app.server.services.impl.UserServiceImpl$$FastClassBySpringCGLIB$$852b5ce2.invoke(<generated>)
                at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
                at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:667)
                at com.app.server.services.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$80381f41.findUserByUsername(<generated>)
                at com.app.server.defautmodel.audit.UserTimeAuditListener.setUpdatedOn(UserTimeAuditListener.java:37)
                at sun.reflect.GeneratedMethodAccessor177.invoke(Unknown Source)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.lang.reflect.Method.invoke(Method.java:498)
                at org.hibernate.jpa.event.internal.ListenerCallback.performCallback(ListenerCallback.java:35)
                at org.hibernate.jpa.event.internal.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:97)
                at org.hibernate.jpa.event.internal.CallbackRegistryImpl.preUpdate(CallbackRegistryImpl.java:71)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.invokeInterceptor(DefaultFlushEntityEventListener.java:350)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.handleInterception(DefaultFlushEntityEventListener.java:332)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:283)
                at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:154)
                at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:235)
                at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:94)
                at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44)

Можете показать код. Также код вашего UserDetailService.

Simon Martinelli 04.01.2019 16:40
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
549
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

По умолчанию все транзакции - это read/write, и, поскольку вы используете @PreUpdate, он всегда будет запускаться для всех транзакций из-за FlushMode в транзакциях read/write. В вашем случае, если вы хотите обойти @PreUpdate в тех случаях, когда вы только извлекаете данные, которые вам нужно указать для своей транзакции, как минимум readOnly, это создаст сеанс гибербации в FlushMode.NEVER, поэтому @PreUpdate не будет запущен. Для большей безопасности в случае, если ваша транзакция встроена в транзакцию pervios, чтобы она унаследовала свои свойства, вы можете использовать Propagation.REQUIRES_NEW, который приостанавливает выполнение предыдущей транзакции, но будьте осторожны с ним, поскольку это может вызвать проблемы с производительностью в более крупных приложениях.

Другие вопросы по теме