Ответ 1
У меня была такая же проблема, и она была исправлена, поместив класс Model
и Model_
в один и тот же пакет.
Я хотел бы использовать API-интерфейс JPA2 с объектами метамодели, что кажется довольно простым:
...
Root<JPAAlbum> albm = cq.from(JPAAlbum.class);
... albm.get(JPAAlbum_.theme) ... ;
но этот Root.get всегда выбрасывает NullPointerException
. JPAAlbum_.theme
был автоматически сгенерирован Hibernate и выглядит как
public static volatile SingularAttribute<JPAAlbum, JPATheme> theme;
но он, очевидно, никогда не заселен.
Я пропустил шаг в инициализации рамки?
РЕДАКТИРОВАТЬ: - это фрагмент того, как я использую JPA и метамодель при ее сбое:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<JPAAlbum> cq = cb.createQuery(JPAAlbum.class) ;
Root<JPAAlbum> albm = cq.from(JPAAlbum.class);
cq.where(cb.equal(albm.get(JPAAlbum_.theme).get(JPATheme_.id),
session.getTheme().getId())) ;
(JPAAlbum_
- класс, поэтому я просто import
раньше) и связанный с ним стек:
Caused by: java.lang.NullPointerException
at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:138)
at net.wazari.dao.jpa.WebAlbumsDAOBean.getRestrictionToAlbumsAllowed(WebAlbumsDAOBean.java:55)
ИЗМЕНИТЬ 2:
В руководстве JBoss EntityManager я вижу, что
Когда строится Hibernate EntityManagerFactory, он будет искать канонический класс метамодели для каждого управляемого типизированного, знает и, если он найдет какой-либо, он будет вводить в них соответствующую метамодельную информацию, как описано в [Спецификация JPA 2, раздел 6.2.2, стр. 200]
Я мог бы также проверить с помощью
for (ManagedType o : em.getMetamodel().getManagedTypes()) {
log.warn("___") ;
for (Object p : o.getAttributes()) {
log.warn(((Attribute)p).getName()) ;
}
}
что Hibernate знает о моей метамодели, имена атрибутов записываются, однако
log.warn("_+_"+JPAPhoto_.id+"_+_") ;
остается отчаянно пустым...
EDIT3: здесь объект JPAAlbum и метамодель.
Что еще я могу рассказать о моей конфигурации...
Я использую Hibernat 3.5.6-Final (согласно META-INF/MANIFEST.MF),
развертывание на Glassfish 3.0.1
от Netbeans 6.9.1;
и приложение полагается на EJB 3.1,
Надеюсь, это поможет!
РЕДАКТИРОВАТЬ 4:
К сожалению, тест JUnit приводит к тому же исключению:
java.lang.NullPointerException
at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:138)
at net.wazari.dao.test.TestMetaModel.foo(TestMetaModel.java:55)
Доступен гораздо более простой проект здесь/tarball. Он содержит только мои сущности и их метамодель плюс тест JUnit (сбой foo с метамоделью, bar в порядке с обычным Query.
РЕДАКТИРОВАТЬ 5:
Вы должны иметь возможность воспроизвести проблему, загрузив tarball, построив проект:
ant compile
or
ant dist
и запустите тест JUnit net.wazari.dao.test.TestMetaModel
CLASSPATH=`sh runTest.sh` java org.junit.runner.JUnitCore net.wazari.dao.test.TestMetaModel
(отредактируйте runTest.sh
, чтобы указать CLASSPATH в нужное место на вашем банке JUnit4-5)
Все связанные с гибернацией зависимости должны быть включены в архив.
У меня была такая же проблема, и она была исправлена, поместив класс Model
и Model_
в один и тот же пакет.
У меня было приложение Java EE 6 с использованием EclipseLink на GlassFish с некоторыми классами @StaticMetamodel, созданными и все работало нормально. Когда я переключился на Hibernate 4 на JBoss 7, я начал получать эти NPE тоже. Я начал расследование, и я нашел эту страницу:
http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/metamodel.html
Он цитирует спецификацию JPA 2, раздел 6.2.1.1, которая определяет, как должны быть созданы статические классы метамодели. Например, я узнал, прочитав спецификацию, что "вариант различных пакетов будет предоставлен в будущей версии этой спецификации". У меня были классы метамодели в разных пакетах, и он отлично работал на EclipseLink, но это дополнительная функция, поскольку текущий стандарт указывает на следующее:
Как только я выполнил все правила в спецификации (приведенное выше просто сводка, см. раздел 6.2.1.1 спецификации для полной версии), я прекратил получать исключения.
Кстати, вы можете скачать спецификацию здесь: http://jcp.org/en/jsr/detail?id=317 (нажмите "Загрузить страницу" для окончательной версии, выберите загрузить спецификацию для оценки, принять соглашение и загрузить файл "SR-000317 2.0 Specification" - persistence-2_0-final-spec.pdf).
Я не могу воспроизвести проблему. Я использовал некоторые из ваших сущностей (упрощенные версии JPAAlbum
, JPATheme
и JPATagTheme
, без каких-либо интерфейсов), сгенерировал классы метамодели, и только следующий простейший тестовый метод (выполняется внутри транзакции) просто передает:
@Test
public void foo() {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<JPAAlbum> query = builder.createQuery(JPAAlbum.class);
Root<JPAAlbum> album = query.from(JPAAlbum.class);
Assert.assertNotNull(album.get(JPAAlbum_.theme)); // no problem here
query.where(builder.equal(album.get(JPAAlbum_.theme).get(JPATheme_.id), 1L));
List<JPAAlbum> results = em.createQuery(query).getResultList();
}
FWIW, вот сгенерированный SQL:
select
jpaalbum0_.ID as ID32_,
jpaalbum0_.AlbumDate as AlbumDate32_,
jpaalbum0_.Description as Descript3_32_,
jpaalbum0_.Nom as Nom32_,
jpaalbum0_.Picture as Picture32_,
jpaalbum0_.Theme as Theme32_
from
Album jpaalbum0_
where
jpaalbum0_.Theme=1
Протестировано с помощью Hibernate EntityManager 3.5.6-Final, Hibernate JPAModelGen 1.1.0.Final, вне любого контейнера.
Мое предложение состояло в том, чтобы сначала попытаться воспроизвести (если воспроизводится) проблему в контексте теста JUnit.
PS: В качестве побочного примечания я не буду хранить сгенерированные классы в VCS.
Обновление: Вот persistence.xml
, который вы можете использовать в контексте тестирования:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="MyPu" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.stackoverflow.q3854687.JPAAlbum</class>
<class>com.stackoverflow.q3854687.JPATheme</class>
<class>com.stackoverflow.q3854687.JPATagTheme</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<!-- Common properties -->
<property name="javax.persistence.jdbc.driver" value="${jdbc.driver}" />
<property name="javax.persistence.jdbc.url" value="${jdbc.url}" />
<property name="javax.persistence.jdbc.user" value="${jdbc.user}" />
<property name="javax.persistence.jdbc.password" value="${jdbc.password}" />
<!-- Hibernate specific properties -->
<property name="hibernate.dialect" value="${jdbc.dialect}" />
<!--
<property name="hibernate.show_sql" value="true"/>
-->
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
Я предлагаю альтернативное решение, если установка модели и модели в том же пакете не работает. Вам нужно добавить один метод init() в ваш класс, который создает SessionFactory или EntityManager:
public class HibernateSessionFactory {
private static SessionFactory factory;
static {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getFactory() {
return factory;
}
public static void init(){} //does nothing but elimating the NULLPOINTEREXCEPTION
}
Поэтому, когда вы запускаете приложение из основного метода или unit test, сначала нужно вызвать HibernateSessionFactory.init();
. Затем NullPointerException волшебным образом исчезает и приложение работает.
Это странное поведение, похоже, происходит, когда вы передаете SingularAttribute
через параметр метода.
Кредит отправляется @Can ÜNSAL, который решил все это в этом вопросе: Hibernate/JPA - исключение NullPointerException при доступе к параметру SingularAttribute