如何使用Hibernate Criteria实现Flight关联Airport两次的SQL查询?
正确实现Hibernate Criteria对应指定SQL查询的方法
原SQL的逻辑是:通过关联flight表与两个airport表(分别对应出发地和目的地),筛选出出发地城镇为minsk、目的地城镇为pinsk的所有航班记录。
常见问题原因
你之前生成的查询出现1=1无效条件,大概率是因为关联实体时未正确设置别名,或者添加筛选条件时引用了错误的属性路径,导致Hibernate无法解析你的条件,最终用1=1替代无效约束。
正确实现方式
首先假设你的实体类结构如下(需与数据库表对应):
Flight实体:包含fromAirport(对应flight.from_id,@ManyToOne关联Airport)、toAirport(对应flight.to_id,@ManyToOne关联Airport)属性Airport实体:包含id、town属性
方式1:使用JPA Criteria API(推荐,兼容JPA规范)
// 获取EntityManager实例(根据你的项目方式获取,比如Spring注入) EntityManager em = ...; CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Flight> cq = cb.createQuery(Flight.class); Root<Flight> flightRoot = cq.from(Flight.class); // 关联出发机场,设置别名a1(内关联,对应SQL的INNER JOIN) Join<Flight, Airport> a1 = flightRoot.join("fromAirport", JoinType.INNER); // 关联到达机场,设置别名a2 Join<Flight, Airport> a2 = flightRoot.join("toAirport", JoinType.INNER); // 添加筛选条件:同时满足出发地是minsk,目的地是pinsk cq.where( cb.and( cb.equal(a1.get("town"), "minsk"), cb.equal(a2.get("town"), "pinsk") ) ); // 执行查询获取结果 List<Flight> flights = em.createQuery(cq).getResultList();
方式2:使用Hibernate原生Criteria API(旧版Session方式)
如果你的项目仍在使用Hibernate的Session API,可按以下方式实现:
// 获取Session实例 Session session = ...; Criteria criteria = session.createCriteria(Flight.class); // 关联出发机场并设置别名a1 criteria.createAlias("fromAirport", "a1"); // 关联到达机场并设置别名a2 criteria.createAlias("toAirport", "a2"); // 添加组合筛选条件 criteria.add(Restrictions.and( Restrictions.eq("a1.town", "minsk"), Restrictions.eq("a2.town", "pinsk") )); // 执行查询 List<Flight> flights = criteria.list();
关键注意点
- 确保实体类中的关联属性名称(比如
fromAirport、toAirport)与你在Criteria中引用的名称完全一致 - 别名(
a1、a2)要在关联时正确设置,且条件中要通过别名引用关联实体的属性 - 如果使用字段名而非属性名(比如直接用
from_id),会导致Hibernate无法映射,同样可能生成无效条件
内容的提问来源于stack exchange,提问作者Singularity
相关产品推荐
相关产品推荐

