JpaRepository выбрасывает EntityNotFoundException вместо возврата null - PullRequest
0 голосов
/ 27 сентября 2018

Я сталкиваюсь с этой очень необычной ошибкой.У меня есть это JpaRepository<SomeObject, Long>

public interface SomeRepository extends JpaRepository<SomeObject, Long> {
      @Query("select someObject from SomeObject someObject where someObject.id = ?1")
     public SomeObject getSomeObject(int id);
}

Это прекрасно работает, и когда я пытаюсь получить SomeObject с ID, который не существует, он просто возвращает ноль, и я обрабатываю его и продолжаю.

Однако, когда я представил несколько экземпляров своего приложения (скажем, 2), и спрятал их за балансировщиком нагрузки.Я выполняю эту операцию (как скрипт), где он извлекает / создает / удаляет SomeObject при повторении.

Когда у меня есть только один экземпляр, я запускаю скрипт, который выполняет: поиск (возвращает ноль) -> созданиеSomeObject, удаление SomeObject и повторный поиск (возвращает ноль) -> ... и т. Д.

Все работает нормально и, как и ожидалось ^

В моей конфигурации с несколькими экземплярами балансировщик нагрузки перенаправляет запросы к экземплярам взаимозаменяемо,Это означает, что теперь операции выполняются в следующем порядке:

Экземпляр (1) поиск (возвращает ноль)

Экземпляр (2) создание SomeObject

Экземпляр (1) удалениеSomeObject

И на следующей итерации наблюдается странное поведение!

Извлечение Instance (2) (здесь вместо того, чтобы возвращать ноль, Spring внезапно выдает следующее исключение):

Caused by: org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find somePackage.SomeObject with id 1; nested exception is javax.persistence.EntityNotFoundException: Unable to find somePackage.SomeObject with id 1
 at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:389) ~[spring-orm-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246) ~[spring-orm-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:488) ~[spring-orm-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) ~[spring-tx-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) ~[spring-tx-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) ~[spring-tx-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133) ~[spring-data-jpa-1.11.3.RELEASE.jar!/:?]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57) ~[spring-data-commons-1.13.3.RELEASE.jar!/:?]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
 at com.sun.proxy.$Proxy201.getSomeObject(Unknown Source) ~[?:?]
 at mypackage.getSomeObject(MyClass.java:111) ~[]

Я уже несколько недель бьюсь головой об стену, пытаясь исправить эту проблему, но не могу понять, почему возникает это исключение EntityNotFoundException.

Исключение составляетправильно, я не понимаю, почему он не возвращает ноль, как обычно.

UPD:

public class SomeObject {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

}

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Как установлено в комментариях, включен кэш второго уровня (EhCache?).

Это приводит к тому, что в примере в вопросе instance (2) считает, что запоминает запрос на созданиекогда приходит второй запрос, но затем удивляется, что не находит совпадение в базе данных.

0 голосов
/ 01 октября 2018

Не готовый полный ответ, но некоторые инструкции о том, как отлаживать подобные вещи (и слишком долго для комментария).

  1. Убедитесь, что у вас есть исходный кодSpring Data JPA, Spring Data Commons и Spring Data ORM доступны и правильно настроены в вашей IDE.

  2. Получите полную трассировку стека полученного исключения (а не только часть, которую вы опубликовали).

  3. На основе трассировки стека милостиво ставить точки останова в коде.

  4. Запустить простой сценарий, который не вызывает исключение в отладчике.,Запомните, какую точку останова вы достигли, а какую нет.

  5. Удалите все точки останова, которые вы достигли, кроме последней.Добавьте больше точек останова между последним, который вы ударили, и первым, который вы пропустили.

  6. Повторяйте до тех пор, пока эти две точки останова не окажутся на расстоянии одного стека.

  7. Отладка оставшегося кода между двумя точками останова в обоих сценариях и наблюдение за различиями.

  8. Вернитесь сюда и расскажите нам, что вы нашли в качестве обновления вопроса или ответа, возможно, включая ссылку на проблему и / или запрос на получение ответа.

...