【问题标题】:java.lang.NoSuchFieldException: factory with hibernate upgradejava.lang.NoSuchFieldException:带有休眠升级的工厂
【发布时间】:2020-04-20 06:10:00
【问题描述】:

我已经将hibernate从5.1.17升级到5.4.11,同时我也升级了hibernate search和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

我在AbstractSessionImpl.class.getDeclaredField("factory"); 收到java.lang.NoSuchFieldException: factory 错误

这是什么原因? Hibernate-search-ormLucene 对于 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;
    }

【问题讨论】:

    标签: hibernate lucene hibernate-search


    【解决方案1】:

    这是什么原因

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

    • 它依赖于一个内部的非 API 类:AbstractSessionImpl。这些类不适合用户访问。
    • 它使用反射来访问其私有字段之一:factory。这些字段不应被用户访问。

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

    您没有提供完整的堆栈跟踪,所以我不知道代码在哪里。 如果代码是你的,你应该找到一个新的 hack。在不知道代码应该做什么的情况下,我无能为力。 如果代码在 Hibernate ORM 或 Search 中,请给出完整的堆栈跟踪。

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

    您使用的版本没问题。如果您想确定,请查看the compatibility matrix。如上所述,问题在于 hack。

    编辑:所以,这是一个 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 的下一个版本中中断。但至少它现在应该可以工作。

    【讨论】:

    • 感谢您的回复。我也在遵循相同的矩阵进行兼容性检查。感谢您的确认。我在我的问题中添加了细节。请检查我的编辑,如果您需要其他任何内容,请告诉我。
    • 可以看到AbstractSessionImpl被修改了,引入了一个新的类AbstractSharedSessionContract作为它的父类。我认为要么我应该更改方法实现,要么我应该使用这个新类。
    • 好的。谢谢你。会尝试让您知道。
    猜你喜欢
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 2013-10-21
    • 1970-01-01
    • 2011-02-01
    • 2021-05-05
    • 2017-02-07
    • 1970-01-01
    相关资源
    最近更新 更多