JPA / Hibernate Static Metamodel attributs non peuplé-NullPointerException

j'aimerais utiliser L'API critères JPA2 avec les objets metamodel, ce qui semble assez facile:

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

mais cette Racine.obtenir jette toujours un NullPointerException. JPAAlbum_.theme a été généré automatiquement par Hibernate et ressemble à

public static volatile SingularAttribute<JPAAlbum, JPATheme> theme;

mais c'est évidemment jamais renseigné.

Suis-je raté une étape dans l'initialisation du cadre ?

EDIT: voici un extrait de comment j'utilise le JPA et le metamodel quand il est s'écraser:

    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_ est une classe, alors j'ai juste import avant) et le stacktrace associé:

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)

EDIT 2:

Dans le JBoss EntityManager guide, je peux voir que

quand L'EntityManagerFactory Hibernate est en cours de construction, il recherchera une classe de métamodèle canonique pour chacune des is gérées et dactylographiées et si elle en trouve une, elle injectera l'information de métamodèle appropriée dans ces spécifications, telles qu'elles sont décrites dans [JPA 2 Specification, section 6.2.2, page 200]

j'ai également pu vérifier avec

     for (ManagedType o : em.getMetamodel().getManagedTypes()) {
            log.warn("___") ;
            for (Object p : o.getAttributes()) {
                log.warn(((Attribute)p).getName()) ;
            }
        }

en veille prolongée est au courant de mon méta-modèle, les noms d'attributs sont écrits, cependant

   log.warn("_+_"+JPAPhoto_.id+"_+_") ;

reste désespérément vide ...

EDIT3 ici jpaalbum entity et son méta-modèle de la classe.

Que puis-je dire d'autre sur ma configuration?..

  • j'utilise Hibernat 3.5.6-Finale (selon META-INF / MANIFEST.MF),

  • déployer sur des poissons de mer3.0.1

  • à partir de Netbeans 6.9.1;

  • et l'application repose sur EJB 3.1,

j'espère que ça va aider !

modifier 4:

malheureusement, le test de JUnit conduit à la même 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)

un projet beaucoup plus simple est disponible ici/archive. il ne contient que mes entities et leur metamodel, plus un test de JUnit (foo crashes with metamodel, bar is okay with the usual Query.

EDIT 5:

Vous devriez être en mesure de reproduire le problème en téléchargeant la archive, construire le projet:

ant compile
or
ant dist

et démarrer le test JUnit net.wazari.dao.test.TestMetaModel

 CLASSPATH=`sh runTest.sh` java org.junit.runner.JUnitCore  net.wazari.dao.test.TestMetaModel

(edit runTest.sh pour point CLASSPATH pour le droit de l'emplacement de votre JUnit4-5 jar)

toutes les dépendances d'hibernation que j'utilise doivent être incluses dans l'archive.

19
demandé sur Kevin 2010-10-04 15:12:42

6 réponses

j'ai eu le même problème et il a été résolu en mettant le Model et Model_ classe dans le même package.

43
répondu debbie 2017-12-25 04:13:55

j'ai eu une application Java EE 6 utilisant EclipseLink sur GlassFish avec quelques classes @StaticMetamodel créées et tout fonctionnait bien. Quand je suis passé à Hibernate 4 sur JBoss 7, j'ai commencé à avoir ces NPE aussi. J'ai commencé à enquêter et j'ai trouvé cette page:

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

il cite la spécification JPA 2, section 6.2.1.1 qui définit comment le métamodèle statique les classes devraient être construites. Par exemple, j'ai découvert en lisant la spécification que "l'option des différents paquets sera fournie dans une future version de cette spécification". J'ai eu les classes metamodel dans différents paquets et cela a bien fonctionné sur EclipseLink, mais c'est une fonctionnalité supplémentaire, comme le standard actuel indique ce qui suit:

  • les classes de métamodèle doivent être dans le même paquet que les classes d'entités qu'elles décrivent;
  • Ils doivent avoir le même nom que le les classes d'entity qu'ils décrivent, suivies d'un underscore (par exemple, Product is the entity, Product_ is the metamodel class);
  • si une entité hérite d'une autre entité ou d'une superclasse cartographiée, sa classe metamodel devrait hériter de la classe metamodel qui décrit sa superclasse immédiate (par exemple si SpecialProduct étend le produit, qui étend PersistentObject, alors SpecialProduct_ devrait étendre le produit qui devrait étendre PersistentObject_).

Une Fois Que J'Ai j'ai suivi toutes les règles du spec (ce qui précède n'est qu'un résumé, veuillez vous reporter à la section 6.2.1.1 du spec pour la version complète), j'ai cessé de recevoir les exceptions.

Par le chemin, vous pouvez télécharger la spécification ici: http://jcp.org/en/jsr/detail?id=317 (cliquez sur "page de Téléchargement" pour la version finale, choisissez de télécharger le cahier des charges pour l'évaluation, l'accepter et télécharger le fichier "SR-000317 2.0" - la persistance 2_0-final-spec.PDF.)

8
répondu Vítor E. Silva Souza 2011-11-10 14:32:43

je ne peux pas reproduire le problème. J'ai utilisé certaines de vos entités (versions simplifiées de JPAAlbum,JPATheme et JPATagTheme, sans aucune interface), a généré les classes metamodel et la méthode de test rudimentaire suivante (qui s'exécute à l'intérieur d'une transaction) vient de passer:

@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, voici le code SQL généré:

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

Testé avec Hibernate EntityManager 3.5.6-Final, Hibernate JPAModelGen 1.1.0.Final, à l'extérieur de n'importe quel conteneur.

ma suggestion serait être d'abord essayer de reproduire (si reproductible) le problème dans un contexte de test de JUnit.

PS: comme note d'accompagnement, Je ne stockerais pas les classes générées dans les VCS.


mise à Jour: Voici un persistence.xml que vous pouvez utiliser dans un cadre test:

<?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>
6
répondu Pascal Thivent 2010-11-08 04:35:17

j'offre une solution alternative si mettre le Model et le Model_ dans le même paquet ne fonctionne pas. Vous devez ajouter une méthode init () à votre classe qui construit le SessionFactory ou 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
}

Ainsi, lorsque vous exécutez votre application à partir de la méthode principale ou d'un test unitaire, vous devez appeler HibernateSessionFactory.init(); dans un premier temps. Puis la NullPointerException disparaît par magie et l'application fonctionne.

c'est Ce comportement étrange semble se produire lorsque vous passez un SingularAttribute autour via le paramètre method.

le mérite en revient à @ Canűsal qui a tout compris dans cette question: Hibernate / JPA-NullPointerException lors de l'accès au paramètre SingularAttribute

0
répondu EliteRaceElephant 2017-05-23 10:31:31

pour info, j'ai rencontré un cas où Hibernate crée un attribut metamodel mais ne l'initialise jamais, conduisant à un