我希望能够在Sping Boot 3.1.2中使用原生Hibernate查询。据我所知,这样做的原因是,HQL可以比JPQL更好地处理嵌套的SELECT(而不是在where)。
我的模型是Bird has OneToMany on HealthCheck HealthCheck has OneToMany on Task(abstract)LengthMeasurements(extends Task)WeightMeasurements(extends Task)
鸟
public class Bird {
private Long id;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "bird")
private List<HealthCheck> listHealthCheck = new ArrayList<>();
健康检查
public class HealthCheck {
private Long id;
@JsonManagedReference
@ManyToOne(fetch = FetchType.EAGER, optional = false)
private Bird bird;
@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy="healthCheck")
private List<Task> tasks;
private LocalDateTime catchDateTime;
长度测量
public class LengthMeasurements extends Task {
private Double beakLength;
private Double legLength;
private Double armWidth;
private Double armDepth;
重量测量
public class WeightMeasurements extends Task {
private Double weight;
抽象类Task意味着我不能使用hibernate路径表达式。
我想最终构建一个查询,获取最近的测量集合的最近(基于检查日期)平均值和最近权重的平均值。
例如:
+---------+-----------+---------------------+------------+-----------+-----------+--------------------+------------+
| bird.id | bird.name | recent measure date | avg length | avg width | avg depth | recent weight date | avg weight |
+---------+-----------+---------------------+------------+-----------+-----------+--------------------+------------+
有一些部分的例子,但他们是旧的和Spring Boot 自动配置干扰了我已经尝试了日期。
为了给予一些关于我到目前为止的尝试的上下文,我有以下代码:
@Repository
public class CustomBirdRepositoryImpl {
@PersistenceContext
private EntityManager entityManager;
final SessionFactory sf = entityManager
.unwrap( Session.class );
public void customHql(Long id) {
Session session = sf.openSession();
String hql = " SELECT MAX(h.catchDateTime), AVG(l.beakLength),
AVG(l.tarsusLength), AVG(l.tarsusWidth), b.name FROM LengthMeasurements l
JOIN l.healthCheck.bird b
JOIN l.healthCheck h
LEFT JOIN (SELECT MAX(w.healthCheck.catchDateTIme), AVG(w.weight), w.healthCheck.bird.id as bid FROM WeightMeasurements w WHERE w.healthCheck.bird.id=1) AS x
ON x.bid = w.healthCheck.bird.id
WHERE b.id=1 GROUP BY b.id, h.id ORDER BY l.healthCheck.catchDateTime DESC LIMIT 1";
org.hibernate.query.Query<BirdDetailsDto> query = session.createQuery(hql);
for(BirdDetailsDto b: query.getResultList()) {
b.toString();
}
}
}
如果我尝试在JPA中运行上面的查询,我会得到:
src\main\java\com\nz\kiwi\repository\BirdRepository.java:54: error: ')' expected
"WHERE b.id = :id ORDER BY l.healthCheck.catchDate DESC LIMIT 1) lm";)
更新
在Hibernate会话中尝试查询时,我得到了更多信息的错误:
Caused by: java.lang.IllegalArgumentException: Component at index 0 has no alias, but alias is required
如何执行此subselect语句?
1条答案
按热度按时间zi8p0yeb1#
事实证明,内部
SELECT
语句在hibernate6中是相对较新的特性。虽然内部的
SELECT
可以独立工作,但在LEFT JOIN
中使用时,这些值需要别名。所以这个片段:
SELECT MAX(w.healthCheck.catchDateTime), AVG(w.weight)
变为SELECT MAX(w.healthCheck.catchDateTime) AS weight_date, AVG(w.weight) AS avg_weight
把它们放在一起:
完整性CustomBirdRepository