有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用CriteriaQuery选择通用主键

从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();

共 (2) 个答案

  1. # 1 楼答案

    我只是设法自己找到了它

    criteriaQuery.select(
        root.get(entityRoot.getModel().getDeclaredId(int.class))
    );
    
  2. # 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以及规范一起使用