jpa Sping Boot 3.1.2子选择查询失败- Hibernate 6.2

ca1c2owp  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(160)

我希望能够在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语句?

zi8p0yeb

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
把它们放在一起:

@Service
@Transactional
public class CustomBirdRepositoryImpl implements CustomBirdRepository {

@PersistenceContext
private EntityManager entityManager;

@Override
public Object customQuery(Long id) {
    return entityManager.createQuery(
                    "SELECT MAX(h.catchDateTime), AVG(l.beakLength), AVG(l.tarsusLength),  AVG(l.tarsusWidth), b.name, b.id, weight_date, avg_weight FROM LengthMeasurements l " +
                            "JOIN l.healthCheck h " +
                            "JOIN h.bird b " +
                            "LEFT JOIN(SELECT MAX(w.healthCheck.catchDateTime) AS weight_date, AVG(w.weight) AS avg_weight, w.healthCheck.bird.id as bid FROM WeightMeasurements w WHERE w.healthCheck.bird.id=:id) AS x " +
                            "ON b.id = x.bid " +
                            "WHERE b.id=:id " +
                            "GROUP BY b.id, h.id ORDER BY l.healthCheck.catchDateTime DESC LIMIT 1")
            .setParameter("id", id)
            .getSingleResult();
    }
}

完整性CustomBirdRepository

@Repository
public interface CustomBirdRepository {
    Object customQuery(Long id);
}

相关问题