首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java.lang.NoSuchFieldException: hibernate升级工厂

java.lang.NoSuchFieldException: hibernate升级工厂
EN

Stack Overflow用户
提问于 2020-04-20 06:10:00
回答 1查看 501关注 0票数 0

我已经将hibernate从5.1.17升级到5.4.11,同时还升级了hibernate搜索和lucene。以下是详细情况

代码语言:javascript
复制
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的建议/兼容是什么?

编辑:这是它引起问题的地方,这段代码存在很长时间。我在运行测试用例时遇到了这个问题,它指向我们代码中的下面的方法。

代码语言:javascript
复制
 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;
    }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-20 08:00:14

会有什么原因

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

  • 它依赖于一个内部的非API类:AbstractSessionImpl。这些类不打算供用户访问。
  • 它使用反射来访问它的一个私有字段:factory。这些字段不打算供用户访问。

简而言之,失败的代码很可能只是一次黑客攻击,而该黑客在Hibernate ORM/Search的最新版本中已不再起作用。

您没有提供完整的堆栈跟踪,所以我不知道代码在哪里。如果代码是你的,你应该找到一个新的黑客。如果不知道代码应该做什么,我就忍不住了。如果代码在Hibernate ORM或Search中,请给出完整的堆栈跟踪。

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

你使用的版本很好。如果您想确定,请查看相容矩阵。正如上面所解释的,问题就在黑客攻击上。

编辑:那么,这是一个黑客。你应该尽可能多地使用SPIs。而不是这样:

代码语言:javascript
复制
            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);

这样做:

代码语言:javascript
复制
            NamedQueryRepository namedQueryRepository = getSessionFactory().unwrap(SessionFactoryImplementor.class)
                        .getNamedQueryRepository()

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

第二部分仍然是一个黑客,仍然是脆弱的,并将有可能突破下一个版本的Hibernate ORM。但至少现在应该有效。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61316099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档