Subcomandante
Subcomandante

Reputation: 403

List of all NamedQueries in JPA

I want to get a list of all NamedQueries within my application and I also want to invoke them generically at runtime. Is there an option to get the list as well as some kind of meta-data (generally speaking some kind of Reflection)?

Another Thread provided some kind of solution for NHibernate ... can't find the similar at JPA even if using Hibernate as implementation.

Thx in advance El Subcomandante

Upvotes: 4

Views: 3099

Answers (3)

Vsevolod Golovanov
Vsevolod Golovanov

Reputation: 4206

Tom Anderson's answer has a mistake: it tries to find annotations on JPA implementation's ManagedType classes, instead of actual entity classes. Here's the corrected version.

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.EntityManagerFactory;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.metamodel.EntityType;

private static Set<NamedQuery> findAllNamedQueries(EntityManagerFactory emf) {
    Set<NamedQuery> allNamedQueries = new HashSet<NamedQuery>();

    Set<EntityType<?>> entityTypes = emf.getMetamodel().getEntities();
    for (EntityType<?> entityType : entityTypes) {
        Class<?> entityClass = entityType.getBindableJavaType();

        NamedQueries namedQueries = entityClass.getAnnotation(NamedQueries.class);
        if (namedQueries != null) {
            allNamedQueries.addAll(Arrays.asList(namedQueries.value()));
        }

        NamedQuery namedQuery = entityClass.getAnnotation(NamedQuery.class);
        if (namedQuery != null) {
            allNamedQueries.add(namedQuery);
        }
    }
    return allNamedQueries;
}

This is still pure JPA2.

Upvotes: 3

Tom Anderson
Tom Anderson

Reputation: 47183

I don't think there's anything that does that in one step built in. But you can do it with the metamodel in JPA2, plus some simple reflection:

private static Set<NamedQuery> findAllNamedQueries(EntityManagerFactory emf) {
    Set<NamedQuery> allNamedQueries = new HashSet<NamedQuery>();

    Set<ManagedType<?>> managedTypes = emf.getMetamodel().getManagedTypes();
    for (ManagedType<?> managedType: managedTypes) {
        if (managedType instanceof IdentifiableType) {
            @SuppressWarnings("rawtypes")
            Class<? extends ManagedType> identifiableTypeClass = managedType.getClass();

            NamedQueries namedQueries = identifiableTypeClass.getAnnotation(NamedQueries.class);
            if (namedQueries != null) {
                allNamedQueries.addAll(Arrays.asList(namedQueries.value()));
            }

            NamedQuery namedQuery = identifiableTypeClass.getAnnotation(NamedQuery.class);
            if (namedQuery != null) {
                allNamedQueries.add(namedQuery);
            }
        }
    }
    return allNamedQueries;
}

Upvotes: 3

seba.wagner
seba.wagner

Reputation: 3860

I don't understand the question, you already given the solution? You simply can scan the classes and use reflection.

This gives you all annotaions of a class. http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getAnnotations%28%29

Now iterate through that list to get NamedQueries. I guess you don't have to scan all your Classes, it is enough if you read your persistance.xml file and only scan your defined Entities.

Here is a detailed example: http://tutorials.jenkov.com/java-reflection/annotations.html

You should be able to cast the Annotation to the NamedQuery and then simply access name/query attributes.

Sebastian

Upvotes: 0

Related Questions