java.lang.NoSuchFieldException:具有休眠升级的工厂

问题描述 投票:0回答:1

我将休眠模式从5.1.17升级到了5.4.11,与此同时,我也升级了休眠搜索和Lucene。下面是详细信息

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-ormLucenehibernate 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;
    }
hibernate lucene hibernate-search
1个回答
0
投票

这是什么原因

假设失败的代码是您自己的,那本质上是不安全的:

  • 它依赖于内部,非API类:AbstractSessionImpl。这些类并不意味着用户可以访问。
  • 它使用反射来访问其私有字段之一:factory。这些字段并不意味着用户可以访问。

简而言之,失败的代码很可能只是一个hack,并且该hack在最新版本的Hibernate ORM / Search中不再起作用。

您没有提供完整的堆栈跟踪,所以我不知道代码在哪里。如果代码是您的代码,则应该找到一个新的技巧。我不知道代码应该做什么。如果代码在Hibernate ORM或Search中,请提供完整的堆栈跟踪。

Hibernate 5.4.11的Hibernate-search-orm和Lucene的建议/兼容性是什么?

您使用的版本很好。如果要确定,请签出the compatibility matrix。如上所述,问题出在hack上。

编辑:所以,这是黑客。应该尽可能多地使用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);

第二部分仍然是hack,仍然很脆弱,并且可能会在下一版本的Hibernate ORM中中断。但是至少现在应该可以。

© www.soinside.com 2019 - 2024. All rights reserved.