Hibernate SQM - 语义查询模型

728 阅读2分钟

简介

在本文中,我将解释什么是Hibernate SQM或语义查询模型,以便你更好地了解Hibernate如何执行JPQL或Criteria API查询。

Hibernate 5、4和3

在Hibernate 6之前,实体查询的执行方式如下。

Hibernate 5 before SQL

Criteria API将简单地生成一个JPQL,Hibernate根据其HQL语法对其进行解析,以生成底层数据库特定的SQL查询。

让Criteria API生成JPQL,然后再进行解析,效率并不高,所以我们设计了一个更好的模型来处理这些实体查询。

Hibernate 6 SQL - 语义查询模型

从Hibernate 6开始,这就是实体查询的生成方式。

Hibernate SQM – Semantic Query Model

JPQL被编译成SQM,而Criteria API则立即创建了SQM节点,因此提高了其效率。

要看到SQM是如何建立的,你必须将org.hibernate.orm.query.sqm.ast 记录器设置为debug

<logger name="org.hibernate.orm.query.sqm.ast" level="debug"/>

并且,在执行以下JPQL窗口函数查询时。

List<StatementRecord> records = entityManager.createQuery("""
    SELECT
       ROW_NUMBER() OVER(       
           PARTITION BY at.account.id
           ORDER BY at.createdOn   
       ) AS nr,
       at,
       SUM(at.amount) OVER(       
           PARTITION BY at.account.id
           ORDER BY at.createdOn   
       ) AS balance
    FROM AccountTransaction at
    ORDER BY at.id
    """, StatementRecord.class)
.unwrap(Query.class)
.setTupleTransformer((Object[] tuple, String[] aliases) -> new StatementRecord(
    longValue(tuple[0]),
    (AccountTransaction) tuple[1],
    longValue(tuple[2])
))
.getResultList();

Hibernate要记录下面的语义查询模型树。

o.h.o.q.s.ast - SqmStatement Tree :
-> [select]
  -> [query-spec]
    -> [select]
      -> [selection(nr)]
      <- [selection(nr)]
      -> [selection]
        -> [root] - `com.vladmihalcea.book.hpjp.hibernate.query.window.AccountTransaction(at)`
        <- [root] - `com.vladmihalcea.book.hpjp.hibernate.query.window.AccountTransaction(at)`
      <- [selection]
      -> [selection(balance)]
      <- [selection(balance)]
    <- [select]
    -> [from]
      -> [root] - `com.vladmihalcea.book.hpjp.hibernate.query.window.AccountTransaction(at)`
      <- [root] - `com.vladmihalcea.book.hpjp.hibernate.query.window.AccountTransaction(at)`
    <- [from]
  <- [query-spec]
<- [select]

Hibernate 6SqmSelectStatement 类实现了Jakarta Persistence TypedQueryCriteriaQuery ,并具有以下依赖性。

SQM Select Statement

通过统一查询模型,Hibernate 6标准查询将能够用特定Jakarta Persistence规范不支持的功能进行扩展,就像Hibernate HQL比标准JPQL规范提供更多的功能一样。

结论

Hibernate 6提供了很多新功能,新的SQM(Semantic Query Model)是一个非常强大的API,是很多新查询功能的基础。

有了Hibernate SQM API,Hibernate就可以提供以前由Blaze Persistence提供的高级查询功能,比如LATERAL JOINsCTE(Common Table Expressions)Window Functions