从Hibernate Criteria API迁移到CriteriaQuery:通用DAO主键查询方法
用CriteriaQuery实现抽象类的主键投影查询
当然可以用CriteriaQuery实现类似Projections.id()的主键查询功能!针对你这种抽象类的通用DAO场景,我来帮你把原来的Hibernate Criteria API代码转换成标准JPA CriteriaQuery的写法,完美适配不同子类主键的需求。
先回顾一下你原来的Criteria API代码:
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();
对应的CriteriaQuery实现代码
下面是功能完全等价的CriteriaQuery版本,同时考虑了抽象类的特性:
EntityManager em = ...; CriteriaBuilder cb = em.getCriteriaBuilder(); // 这里根据你的主键类型指定泛型,如果子类主键类型不统一,可以用Object代替Integer CriteriaQuery<Integer> cq = cb.createQuery(Integer.class); Root<MyEntity> root = cq.from(MyEntity.class); // 对应原来的Restrictions.in过滤条件 cq.where(root.get("accountID").in(accounts)); // 对应原来的Projections.id(),选择实体的主键 cq.select(root.get("id")); // 执行查询 List<Integer> list = em.createQuery(cq).getResultList();
关键细节说明
- 主键选择的灵活性:如果你的不同子类主键类型不同(比如有的是
Integer,有的是Long或String),可以把CriteriaQuery<Integer>改成CriteriaQuery<Object>,这样能兼容所有类型的主键结果。 - 类型安全优化:如果项目中使用了JPA元模型(通过注解处理器生成的
MyEntity_类),可以把root.get("id")换成root.get(MyEntity_.id),避免硬编码字符串字段名,减少出错概率。 - 抽象类的处理:Hibernate会自动识别抽象类对应的子类,在执行查询时会正确关联子类的主键字段,不需要额外配置。
泛型通用DAO的扩展思路
如果这是通用DAO的一部分,你可以把它封装成泛型方法,适配任意抽象实体类:
public <T, ID> List<ID> findIdsByAccountIds(Class<T> entityClass, Collection<?> accounts) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<ID> cq = cb.createQuery((Class<ID>) Object.class); Root<T> root = cq.from(entityClass); cq.where(root.get("accountID").in(accounts)); cq.select(root.get("id")); return em.createQuery(cq).getResultList(); }
这样不管你的抽象类子类主键是什么类型,都能直接调用这个方法获取对应的主键列表。
内容的提问来源于stack exchange,提问作者Jeppz
相关产品推荐
相关产品推荐

