JPA / Hibernate静态元模型属性未填充 – NullPointerException

我想将JPA2 Criteria API与元模型对象一起使用,这看起来很简单:

... Root albm = cq.from(JPAAlbum.class); ... albm.get(JPAAlbum_.theme) ... ; 

但是这个Root.get总是抛出一个NullPointerExceptionJPAAlbum_.theme是由Hibernate自动生成的,看起来像

 public static volatile SingularAttribute theme; 

但它显然从未填充过。

我错过了框架初始化的一步吗?

编辑:这是我在崩溃时如何使用JPA和元模型的片段:

  CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(JPAAlbum.class) ; Root albm = cq.from(JPAAlbum.class); cq.where(cb.equal(albm.get(JPAAlbum_.theme).get(JPATheme_.id), session.getTheme().getId())) ; 

JPAAlbum_是一个类,所以我只是import之前)和相关的JPAAlbum_

 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]

我也可以validation

  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测试导致了同样的exception:

 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与metamodel崩溃,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 jar的正确位置)

我使用的所有hibernate依赖项都应该包含在归档中。

我有同样的问题,并通过将ModelModel_类放入同一个包中来解决。

我在GlassFish上使用EclipseLink创建了一个Java EE 6应用程序,并创建了一些@StaticMetamodel类,一切正常。 当我在JBoss 7上切换到Hibernate 4时,我也开始使用这些NPE。 我开始调查,我找到了这个页面:

http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/metamodel.html

它引用了JPA 2规范的第6.2.1.1节,它定义了如何构建静态元模型类。 例如,我通过阅读规范发现“将在本规范的未来版本中提供不同包的选项”。 我在不同的包中使用了元模型类,它在EclipseLink上运行良好,但它是一个额外的function,因为当前标准表明如下:

  • 元模型类应与它们描述的实体类位于同一个包中;
  • 它们应该与它们描述的实体类具有相同的名称,后跟下划线(例如,Product是实体,Product_是元模型类);
  • 如果实体inheritance自另一个实体或映射的超类,则其元模型类应inheritance描述其直接超类的元模型类(例如,如果SpecialProduct扩展了Product,它扩展了PersistentObject,那么SpecialProduct_应该扩展Product_,它应该扩展PersistentObject_)。

一旦我遵循规范中的所有规则(上面只是一个摘要,请参阅完整版本规范的第6.2.1.1节),我就停止了例外。

顺便说一下,你可以在这里下载规范: http : //jcp.org/en/jsr/detail?id = 317 (点击“下载页面”获取最终版本,选择下载规范进行评估,接受协议并下载文件“SR-000317 2.0 Specification” – persistence-2_0-final-spec.pdf)。

我无法重现这个问题。 我使用了你的一些实体( JPAAlbumJPAThemeJPATagTheme简化版本,没有任何接口),生成了元模型类,以及下面的基本测试方法(在事务中运行)只传递:

 @Test public void foo() { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery query = builder.createQuery(JPAAlbum.class); Root 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 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

    org.hibernate.ejb.HibernatePersistence com.stackoverflow.q3854687.JPAAlbum com.stackoverflow.q3854687.JPATheme com.stackoverflow.q3854687.JPATagTheme true               

如果将Model和Model_放在同一个包中不起作用,我会提供另一种解决方案。 您需要向构建SessionFactory或EntityManager的类添加一个init()方法:

 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 } 

因此,当您从main方法或unit testing运行应用程序时,您需要调用HibernateSessionFactory.init(); 第一。 然后NullPointerException神奇地消失,应用程序工作。

当您通过方法参数传递SingularAttribute时,似乎会发生这种奇怪的行为。

归功于@CanÜNSAL,他在这个问题中想到了这一点: Hibernate / JPA – 访问SingularAttribute参数时出现NullPointerException

仅供参考,我遇到过Hibernate创建元模型属性但从未初始化它的情况,在尝试使用它时会导致NullPointerException

 public class Upper { public String getLabel() { return this.label; } public void setLabel(String label) { this.label = label; } } public class Lower extends Upper { @Override public String getLabel() { return super.getLabel(); } } 

Hibernate在两个类中生成label属性声明:

 @Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor") @StaticMetamodel(Upper.class) public abstract class Upper_ { public static volatile SingularAttribute label; } @Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor") @StaticMetamodel(Lower.class) public abstract class Lower_ { public static volatile SingularAttribute label; } 

…它将初始化Upper_.label但将Lower_.label等于null。

繁荣

类和metaModel应该在同一个包中,即

文件夹实体:

  • 埃赫
  • Eje_
  • 元件
  • 元件_

我附上了元模型代码的一个例子

 import javax.annotation.Generated; import javax.persistence.metamodel.SetAttribute; import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.StaticMetamodel; import java.util.Date; @Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor") @StaticMetamodel(Eje.class) public abstract class Eje_ { public static volatile SingularAttribute id; public static volatile SingularAttribute name; public static volatile SingularAttribute users; public static volatile SingularAttribute createdAt; public static volatile SingularAttribute updatedAt; public static volatile SetAttribute factorCriticos; }