Запуск NativeQuery в цикле не возвращает правильные данные

#java #hibernate #jpa #entitymanager

#java #спящий режим #jpa #entitymanager

Вопрос:

Я пытаюсь запустить собственный запрос в цикле, запрос отображает правильный синтаксис sql, но результат всегда один и тот же.

     for (int i=0; i<translations.size(); i  ) {
        Query query = entityManager.createNativeQuery("Select * from "   translations.get(i).getName(), MyModel.class);
        rows = (List<MyModel>)query.getResultList();
        // rest of the function...
    }
  

теперь в консоли я вижу операторы гибернации, такие как:

 Hibernate: Select * from translation1
Hibernate: Select * from translation2
Hibernate: Select * from translation3
  

но переменная «rows» всегда содержит результат первого оператора select, т.е. Строки таблицы translation1.

Есть идеи, почему в консоли он показывает, что он также выбирает из других таблиц, но на самом деле он всегда получает данные из таблицы translation1?

Комментарии:

1. У вас одинаковые значения полей идентификаторов в этих таблицах?

2. на самом деле невозможно ответить на это, не видя везде, что rows используется. Например, почему не rows объявлено в цикле for?

3. @axtavt да, все таблицы имеют одинаковые идентификаторы и одинаковые имена столбцов, за исключением одного столбца, rowText, он содержит текст на разных языках в зависимости от таблицы преобразования.

Ответ №1:

Если все таблицы имеют одинаковый набор идентификаторов, это ожидаемое поведение.

Кэш сеанса гибернации гарантирует, что внутри сеанса может быть только один экземпляр объекта определенного типа с определенным идентификатором. Поскольку сущности разрешаются через кэш сеанса даже в случае собственного запроса, вы получаете те же экземпляры.

Итак, у вас есть несколько вариантов:

  • переосмыслите схему вашей базы данных
  • создайте объекты из результата запроса вручную
  • принудительно очистите кэш сеанса, вызвав clear() или detach()

Комментарии:

1. спасибо за помощь, я не могу изменить схему БД, EntityManager.clear() исправил проблему.

2. @user908452: обратите внимание, что clear() удаляет все объекты из кэша сеанса, что может привести к неожиданным побочным эффектам, если некоторые из этих объектов были загружены другими методами. Возможно, было бы лучше использовать detach() для явного удаления только только что загруженных объектов.

Ответ №2:

Вы уверены, что переменная rows на самом деле не содержит ПОСЛЕДНИЙ из ваших возвращенных результатов? как вы инициализируете строки и что вы делаете с переменной внутри цикла? Если вы хотите получить все результаты от всех запросов, вам нужно добавить каждый из них (внутри цикла) в переменную list / set, объявленную ПЕРЕД запуском цикла.

Или вы могли бы использовать какой-нибудь правильный SQL и сделать:

 SELECT * FROM Table1 [JOIN/UNION] Table2 etc...
  

Комментарии:

1. Я уверен, что переменная rows НЕ содержит последних данных, я инициализировал ее вне цикла, но я попытался инициализировать ее и внутри цикла, и все равно это не сработало. Я перебираю ArrayList строк и добавляю его в Map Карты.