【问题标题】:Selecting generic primary key with CriteriaQuery使用 CriteriaQuery 选择通用主键
【发布时间】:2018-11-04 14:46:45
【问题描述】:

当从 Hibernate Criteria api 迁移到 CriteriaQuery 时,我遇到了一个抽象类的通用 DAO,它在公共字段上有一个 where 但在其 id 上执行选择,即使每个类的 id 完全不同。

旧投影是这样的

criteria.setProjection(Projections.id());

有没有办法用 CriteriaQuery 以类似的方式做到这一点?

编辑:完整标准代码

DetachedCriteria detachedCriteria = DetachedCriteria.forClass(MyEntity.class);
detachedCriteria.add(Restrictions.in("accountID", accounts));
detachedCriteria.setProjection(Projections.id());

EntityManager em = ...;
Criteria criteria = detachedCriteria.getExecutableCriteria((Session) em.getDelegate());
List<Integer> list = criteria.list();

【问题讨论】:

  • 我们需要查看完整的查询
  • @JEY 从这段代码运行的休眠查询看起来像这样“休眠:从配置文件 this_ 中选择 TOP(?) this_.profilePK as y0_ where this_.accountID in (?)”所以真的没有很重要。
  • 没有完整的标准
  • @JEY 我添加了完整的标准..

标签: java hibernate jpa criteriaquery


【解决方案1】:

我自己找到的。

criteriaQuery.select(
    root.get(entityRoot.getModel().getDeclaredId(int.class))
);

【讨论】:

    【解决方案2】:

    组合答案:

    https://stackoverflow.com/a/16911313

    https://stackoverflow.com/a/47793003

    我创建了这个方法:

    public String getIdAttribute(EntityManager em, String fullClassName) {
        Class<? extends Object> clazz = null;
        try {
            clazz = Class.forName(fullClassName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Metamodel m = em.getMetamodel();
        IdentifiableType<T> of = (IdentifiableType<T>) m.managedType(clazz);
        return of.getId(of.getIdType().getJavaType()).getName();
    }
    

    然后我注入了实体管理器

    @PersistenceContext
    private EntityManager em;
    

    我得到这样的根实体主键:

    String rootFullClassName = root.getModel().getJavaType().getName();
    String primaryKeyName = getIdAttribute(em, rootFullClassName);
    

    我得到了这样的属性引用的主键:

    return (Specification<T>) (root, query, builder) -> {
        Set<Attribute<? super T, ?>> attributes = root.getModel().getAttributes();
        for (Attribute a: attributes) {
            if(a.isAssociation()) { 
                Path rootJoinGetName = root.join(a.getName());
                String referencedClassName = rootJoinGetName.getJavaType().getName();
                String referencedPrimaryKey = getIdAttribute(em, referencedClassName);
                //then I can use it to see if it is equal to a value (e.g 
                //filtering actors by movies with id = 1 - in 
                //this case referencedPrimaryKey is "id")
                Predicate p = rootJoinGetName.get(referencedPrimaryKey).in(1);
            }
        }
    }
    

    这样我不需要提前知道主键/引用键的类型,因为它可以通过实体管理器元模型导出。上面的代码可以与 CriteriaQuery 以及 Specifications 一起使用。

    【讨论】:

      猜你喜欢
      • 2014-12-20
      • 2016-09-26
      • 2015-06-29
      • 1970-01-01
      • 1970-01-01
      • 2021-01-04
      • 1970-01-01
      • 1970-01-01
      • 2013-12-31
      相关资源
      最近更新 更多