JPA 中所有 NamedQueries 的列表

Posted

技术标签:

【中文标题】JPA 中所有 NamedQueries 的列表【英文标题】:List of all NamedQueries in JPA 【发布时间】:2012-09-27 05:54:32 【问题描述】:

我想在我的应用程序中获取所有 NamedQueries 的列表,并且我还想在运行时通用地调用它们。是否可以选择获取列表以及某种元数据(一般来说是某种反射)?

另一个线程为 NHibernate 提供了某种解决方案......即使使用 Hibernate 作为实现,在 JPA 也找不到类似的解决方案。

提前谢谢 副指挥官

【问题讨论】:

您需要了解实现的细节。 DataNucleus JPA 将提供一种足够简单的方法,但不知道 Hibernate 【参考方案1】:

我认为没有任何东西可以一步完成。但是你可以使用 JPA2 中的元模型,加上一些简单的反射来做到这一点:

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;

【讨论】:

诅咒!如果不查找和解析 XML 文件,我看不到任何方法,这听起来并不有趣。 hmmm,完成这些事情看起来不是很有趣......我在想 Adam Bien 在他的 Pattern book 中提供的一些东西(@see:adam-bien.com/roller/abien/entry/generic_crud_service_aka_dao,该方法的签名: public List findWithNamedQuery(String namedQueryName, Map parameters,int resultLimit)) 并且提前知道(至少对于 UI 组件)存在哪些命名查询并动态调用它们“某种反射样式”可能会有所帮助.【参考方案2】:

Tom Anderson 的回答有一个错误:它试图在 JPA 实现的 ManagedType 类上查找注释,而不是实际的实体类。这是修正后的版本。

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;

这仍然是纯 JPA2。

【讨论】:

我尝试编辑汤姆的答案,但审稿人不知道他们在做什么:***.com/review/suggested-edits/9231490 如果我直接在实体管理器工厂上添加命名查询,这是否有效,例如emf.addNamedQuery("State.all", em.createNamedQuery("FROM com.my.State", State.class));.? @bonapart3,值得怀疑,因为这是通过查看注释来实现的。 Hibernate中有一个NamedQueryRepository类,可以从SessionFactory获取,然后可以使用反射读取其namedQueryDefinitionMap字段(Hibernate 5.3.7会这样)。【参考方案3】:

我不明白这个问题,你已经给出了解决方案? 您只需扫描类并使用反射即可。

这会给你一个类的所有注释。 http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getAnnotations%28%29

现在遍历该列表以获取 NamedQueries。 我想你不必扫描所有的类,如果你阅读你的persistance.xml 文件并且只扫描你定义的实体就足够了。

这里有一个详细的例子: http://tutorials.jenkov.com/java-reflection/annotations.html

您应该能够将 Annotation 转换为 NamedQuery,然后简单地访问名称/查询属性。

塞巴斯蒂安

【讨论】:

假设你有超过 10 个 arćhives 和数百个类,这似乎并不容易解决。

以上是关于JPA 中所有 NamedQueries 的列表的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法获取带有结果集的 JPA 命名查询的计数大小?

JPA .find()变异实例

JPA命名查询中的多对一关系

JPA Group by 具有多个字段

JPA 命名查询与 group by 参数名和值

JPA NamedQuery 与聚合函数和分组依据一起使用