[ManagedType] не найден для ключевого класса для Spring Data и Eclipselink в Java 11 - PullRequest
0 голосов
/ 16 октября 2018

В моем проекте я использую Spring Data Lovelace, Spring 5.1.1 и Eclipselink 2.7.3 со статическим переплетением с помощью плагина com.ethlo.persistence.tools:eclipselink-maven-plugin:2.7.1.1.Кроме того, я использую OpenJDK 11.

Сборка работает нормально, и eclipselink-maven-plugin выполняется.Он генерирует persistence.xml, который мне подходит.

Но когда я запускаю тесты, я получаю

Caused by: java.lang.IllegalArgumentException: No [ManagedType] was found for the key class [com.example.MyEntity] in the Metamodel - please verify that the [Managed] class was referenced in persistence.xml using a specific <class>com.example.MyEntity</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
    at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.entityEmbeddableManagedTypeNotFound(MetamodelImpl.java:180)
    at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:527)
    at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:74)
    at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:188)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:139)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:123)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:64)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:305)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297)
    at org.springframework.data.util.Lazy.getNullable(Lazy.java:211)
    at org.springframework.data.util.Lazy.get(Lazy.java:94)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:119)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1804)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1741)
    ... 57 more

Я уже пробовал:

  • Использование Java 8: это решает проблему, но я хочу использовать Java 11.
  • Вставка <exclude-unlisted-classes>false</exclude-unlisted-classes> в persistence.xml вручную: без разницы, но опять же, это свойство «Не применимо к JavaЕдиницы персистентности SE "anyways
  • Установка свойства eclipselink.weaving jpa на false, как в примере проекта Spring Data Eclipselink : без разницы

Обновление: Я отладил инициализацию eclipselink, и она не "знает" мои классы сущностей.В MetadataProcessor#initPersistenceUnitClasses они появляются (поэтому persistence.xml правильно принимается) в списке classNames.Затем Eclipselink выполняет итерацию по всем найденным именам классов и (среди прочих) пытается найти аннотацию @Entity, вызывая PersistenceUnitProcessor.isEntity(..), что, в свою очередь, вызывает candidateClass.isAnnotationPresent("javax.persistence.Entity") - и возвращает false.

Другими словами:Основная проблема, по-видимому, заключается в том, что Eclipselink не может видеть аннотацию @Entity на моих классах сущностей (которые присутствуют, конечно).

Обновление 2: Iвключил ведение журнала eclipselink, вставив <property name="eclipselink.logging.level" value="ALL"/> в файл persistence.xml и получив следующие выходные данные:

[EL Warning]: metamodel: 2018-10-17 08:15:13.449--The collection of metamodel types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element
[EL Warning]: metamodel: 2018-10-17 08:15:13.464--The collection of metamodel [ManagedType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [class de.viaprinto.backoffice.elasticsearch.persistence.entity.ElasticsearchIndex] will return null.
[EL Warning]: metamodel: 2018-10-17 08:15:13.464--The collection of metamodel [ManagedType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units.  Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.  The lookup on [class de.viaprinto.backoffice.elasticsearch.persistence.entity.ElasticsearchIndex] will return null.

Так что никакой новой информации там нет.

Обновление 3: Сгущение заговора: я выяснил, как eclipselink создает свои метаданные класса (в которых он не может найти аннотацию @Entity).Для этого он использует ASM вместо отражения.Чтобы быть более точным, он использует собственную переупакованную версию (в данном случае) ASM 6.2 (переупакованную как org.eclipse.persistence:org.eclipse.persistence.asm:2.7.3).После правильного нахождения аннотации (в ClassReader:626) он пытается Visit the NestedMembers attribute (ClassReader:651), и это завершается с UnsupportedOperationException.Eclipselink перехватывает это исключение и добавляет «класс виртуальных метаданных» (MetadataAsmFactory:143), который не содержит информации аннотации.

Я обнаружил проблему в трекере проблем Spring , которая, кажется, описывает точно то же самоепроблема.Их решение состояло в том, чтобы включить экспериментальную поддержку ASM 7.Пока не знаю, как это сделать в eclipselink.

Мои классы сущностей содержат вложенный класс (точнее, enum), который, кажется, вызывает проблему.

1 Ответ

0 голосов
/ 17 октября 2018

Eclipselink использует ASM для анализа классов сущностей и генерации метаданных, которые, в свою очередь, используются для определения того, является ли класс сущностей сущностью (то есть несет аннотацию @Entity).

При обнаружении "вложенного"член "(т.е. вложенное перечисление) в моих классах сущностей, ASM 6.2 выбрасывает UnsupportedOperationException, который заставляет eclipselink отбрасывать уже собранные метаданные для этого класса и генерировать фиктивные метаданные, которые не содержат аннотаций.Отсюда и ошибка.

Существует четыре способа исправить это:

  1. Пока не используйте вложенные классы в классах сущностей
  2. Скомпилируйте свою собственную версию eclipselink, гдеВы устанавливаете уровень API ASM на ASM7_EXPERIMENTAL в конструкторе eclipselink MetadataAsmFactory$ClassMetadataVisitor.Я не проверял это, но согласно this это должно решить проблему.
  3. Используйте более низкий уровень байт-кода (теоретически, должно работать 9 или 10).Опять же, я не проверял это, но согласно this это должно исправить проблему.
  4. Использовать другого поставщика JPA

По-видимому, это уже исправлено вмастер eclipselink и его ветка 2.7, поэтому исправление должно быть доступно в следующем выпуске.

...