java .lang.NoSuchFieldException: фабрика с обновлением гибернации - PullRequest
0 голосов
/ 20 апреля 2020

Я обновил режим гибернации с 5.1.17 до 5.4.11, а также улучшил поиск в спящем режиме и люцен. Ниже приведены подробности

Hibernate: 5.1.17 to 5.4.11
Hibernate-search-orm: 5.5.2 to 5.11.5
Lucene:  5.3.1 to 5.5.5

Я получаю java.lang.NoSuchFieldException: factory ошибку при AbstractSessionImpl.class.getDeclaredField("factory");

Что может быть причиной для этого? Каковы рекомендуемые / совместимые Hibernate-search-orm и Lucene для hibernate 5.4.11 ??

РЕДАКТИРОВАТЬ: Это, где это вызывает проблему, и этот код существует в течение длительного времени. Я получил эту проблему при выполнении тестовых случаев, и он указывает на метод ниже в нашем коде.

 private Set<String> getAllQueryNames() {
        Set<String> queryNames = Sets.newHashSet();
        try {
            Field factoryField = AbstractSessionImpl.class.getDeclaredField("factory");
            factoryField.setAccessible(true);
            SessionFactoryImpl factory = (SessionFactoryImpl) factoryField.get(getSessionFactory().getCurrentSession());
            Field namedQueriesField = SessionFactoryImpl.class.getDeclaredField("namedQueryRepository");
            namedQueriesField.setAccessible(true);
            NamedQueryRepository namedQueryRepository = (NamedQueryRepository) namedQueriesField.get(factory);

            Field namedQueryDefinitionMapField = NamedQueryRepository.class.getDeclaredField("namedQueryDefinitionMap");
            namedQueryDefinitionMapField.setAccessible(true);
            Map namedQueryDefinitionMap = (Map) namedQueryDefinitionMapField.get(namedQueryRepository);


            queryNames.addAll(namedQueryDefinitionMap.keySet());

        } catch (SecurityException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

        return queryNames;
    }

1 Ответ

1 голос
/ 20 апреля 2020

Что может быть причиной для этого

Предполагая, что код, который не удался, принадлежит вам, он по сути небезопасен:

  • Он опирается на внутренний , класс не-API: AbstractSessionImpl. Эти классы не предназначены для доступа пользователей.
  • Он использует отражение для доступа к одному из своих частных полей: factory. Эти поля не предназначены для доступа пользователей.

Короче говоря, код, который не работает, скорее всего, просто взлом, и этот взлом больше не работает в последних версиях Hibernate ORM / Search.

Вы не предоставили полную трассировку стека, поэтому я не знаю, где находится код. Если код ваш, вы должны найти новый взломать. Я не могу помочь, не зная, что должен делать код. Если код находится в Hibernate ORM или Search, укажите полную трассировку стека.

Каковы рекомендуемые / совместимые Hibernate-search-orm и Lucene для hibernate 5.4.11 ??

Версии, которые вы используете, в порядке. Если вы хотите быть уверены, проверьте матрицу совместимости . Проблема заключается во взломе, как объяснено выше.

РЕДАКТИРОВАТЬ: Итак, это взлом. Вместо этого вы должны использовать SPI, насколько это возможно. Вместо этого:

            Field factoryField = AbstractSessionImpl.class.getDeclaredField("factory");
            factoryField.setAccessible(true);
            SessionFactoryImpl factory = (SessionFactoryImpl) factoryField.get(getSessionFactory().getCurrentSession());
            Field namedQueriesField = SessionFactoryImpl.class.getDeclaredField("namedQueryRepository");
            namedQueriesField.setAccessible(true);
            NamedQueryRepository namedQueryRepository = (NamedQueryRepository) namedQueriesField.get(factory);

            Field namedQueryDefinitionMapField = NamedQueryRepository.class.getDeclaredField("namedQueryDefinitionMap");
            namedQueryDefinitionMapField.setAccessible(true);
            Map namedQueryDefinitionMap = (Map) namedQueryDefinitionMapField.get(namedQueryRepository);

Сделайте это:

            NamedQueryRepository namedQueryRepository = getSessionFactory().unwrap(SessionFactoryImplementor.class)
                        .getNamedQueryRepository()

            Field namedQueryDefinitionMapField = NamedQueryRepository.class.getDeclaredField("namedQueryDefinitionMap");
            namedQueryDefinitionMapField.setAccessible(true);
            Map namedQueryDefinitionMap = (Map) namedQueryDefinitionMapField.get(namedQueryRepository);

Вторая часть по-прежнему является хаком, по-прежнему fr agile и потенциально может сломаться в следующих версиях Hibernate ОРМ. Но, по крайней мере, пока это должно работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...