java.lang.NoSuchFieldException:带休眠升级的工厂
java.lang.NoSuchFieldException: factory with hibernate upgrade
我已将 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-orm
的suggested/compatible和hibernate 5.4.11
的Lucene
是什么??
编辑:这是导致问题的地方,并且此代码存在已久。
我在 运行 测试用例时遇到了这个问题,它指向我们代码中的以下方法。
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;
}
What would be reason for this
假设失败的代码是你的,它本质上是不安全的:
- 它依赖于内部,非API class:
AbstractSessionImpl
。这些 class 不应该被用户访问。
- 它使用反射来访问其 私有 字段之一:
factory
。这些字段不应该被用户访问。
简而言之,失败的代码可能只是一个 hack,并且该 hack 在最新版本的 Hibernate 中不再有效 ORM/Search。
你没有提供完整的堆栈跟踪,所以我不知道代码在哪里。
如果代码是你的,你应该找到一个新的 hack。如果不知道代码应该做什么,我无能为力。
如果代码在 Hibernate ORM 或 Search 中,请提供完整的堆栈跟踪。
What are the suggested/compatible of Hibernate-search-orm and Lucene for hibernate 5.4.11??
您使用的版本没问题。如果您想确定,请查看 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 中仍有可能被破坏。但至少它现在应该可以工作。
我已将 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-orm
的suggested/compatible和hibernate 5.4.11
的Lucene
是什么??
编辑:这是导致问题的地方,并且此代码存在已久。 我在 运行 测试用例时遇到了这个问题,它指向我们代码中的以下方法。
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;
}
What would be reason for this
假设失败的代码是你的,它本质上是不安全的:
- 它依赖于内部,非API class:
AbstractSessionImpl
。这些 class 不应该被用户访问。 - 它使用反射来访问其 私有 字段之一:
factory
。这些字段不应该被用户访问。
简而言之,失败的代码可能只是一个 hack,并且该 hack 在最新版本的 Hibernate 中不再有效 ORM/Search。
你没有提供完整的堆栈跟踪,所以我不知道代码在哪里。 如果代码是你的,你应该找到一个新的 hack。如果不知道代码应该做什么,我无能为力。 如果代码在 Hibernate ORM 或 Search 中,请提供完整的堆栈跟踪。
What are the suggested/compatible of Hibernate-search-orm and Lucene for hibernate 5.4.11??
您使用的版本没问题。如果您想确定,请查看 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 中仍有可能被破坏。但至少它现在应该可以工作。