JPA Criteria API查询子类属性的MoralEntity报错求助
问题解决:Hibernate Criteria查询无法识别子类属性
错误原因
报错核心在于PartnerEntity本身没有specialities属性,仅其子类Entity1和Entity2拥有该属性。原查询未先过滤实体类型,Hibernate会尝试对所有PartnerEntity实例(包括无specialities的Entity3)解析该属性,从而抛出无法解析属性的异常。
修正后的Criteria查询代码
CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<MoralEntity> query = cb.createQuery(MoralEntity.class); Root<MoralEntity> root = query.from(MoralEntity.class); Join<MoralEntity, PartnerEntity> partnerJoin = root.join("partner"); // 处理Entity1的条件:先限定类型,再关联specialities Path<Entity1> entity1Path = cb.treat(partnerJoin, Entity1.class); Join<Entity1, SpecialityEntity> specialityJoin1 = entity1Path.join("specialities"); Predicate entity1Predicate = cb.and( cb.equal(partnerJoin.get("pType"), "E1"), cb.equal(specialityJoin1.get("code"), "ABC") ); // 处理Entity2的条件:同样先限定类型,再关联specialities Path<Entity2> entity2Path = cb.treat(partnerJoin, Entity2.class); Join<Entity2, SpecialityEntity> specialityJoin2 = entity2Path.join("specialities"); Predicate entity2Predicate = cb.and( cb.equal(partnerJoin.get("pType"), "E2"), cb.equal(specialityJoin2.get("code"), "ABC") ); // 组合两个条件 query.where(cb.or(entity1Predicate, entity2Predicate)); List<MoralEntity> resultList = em.createQuery(query).getResultList();
另一种更简洁的JPQL写法
如果允许使用JPQL,可读性会更强:
SELECT m FROM MoralEntity m WHERE ( TYPE(m.partner) = Entity1 AND EXISTS ( SELECT s FROM m.partner.specialities s WHERE s.code = 'ABC' ) ) OR ( TYPE(m.partner) = Entity2 AND EXISTS ( SELECT s FROM m.partner.specialities s WHERE s.code = 'ABC' ) )
关键改进点
- 先过滤实体类型:通过
pType字段或TYPE()函数,先限定只处理拥有specialities属性的子类,避免Hibernate在父类或无该属性的子类上无效解析。 - 明确treat后的实体路径:将
treat转换后的实体路径赋值给变量,让Hibernate清晰识别目标子类的属性,避免解析混淆。
内容的提问来源于stack exchange,提问作者Aymen Kanzari
相关产品推荐
相关产品推荐

