Select

select 允许我们控制在图表的根级别获取的属性。我们可以指定仅选择一些属性进行获取。结果是部分填充的 Bean。

// "alias" bean that can be used in select and fetch clauses
QCustomer cust = QCustomer.alias();

List<Customer> customers =
  new QCustomer()
    // only fetch some properties of customer (partial objects)
    .select(cust.name, cust.version, cust.whenCreated)
    .name.istartsWith("Rob")
    .findList();

通过上述内容,我们指定了要获取的属性。我们仍然获得返回的 Customer 实体 Bean,但它们是部分填充的

上述查询生成的 SQL 具有

select t0.id, t0.name, t0.registered, t0.version from customer t0

请注意,对于大多数查询,@Id 属性会自动包含,而对于distinctfindSingleAttributeaggregation 查询,它会自动排除。

使用查询 Bean 定义选择属性提供了一种类型安全的方法来定义要获取的对象图的哪一部分。

使用查询表达式 API 编写的相同查询是

List<Customer> customers =
  database.find(Customer.class)
    .select("name, registered, version")
    .findList();

alias() - 指定属性

每个查询 Bean 都具有一个静态 alias() 方法,该方法返回一个查询 Bean,我们使用该 Bean 在 select()fetch() 中指定要获取的属性。

// customer "alias"
QCustomer cust = QCustomer.alias();

// contact "alias"
QCustomer con = QContact.alias();

List<Customer> customers =
  new QCustomer()

    .select(cust.name, cust.version, cust.whenCreated)
    .contacts.fetch(con.firstName, con.LastName, con.email)

    .name.istartsWith("Rob")
    .findList();

在上面,我们有客户和联系人的别名 Bean。我们使用它们来指定我们要获取的特定属性。

请注意,我们可以将 alias() 分配给静态 final 字段。

private static final QCustomer CUST = QCustomer.alias();
...
List<Customer> customers =
  new QCustomer()
    .select(CUST.name)
    .name.istartsWith("Rob")
    .findList();

静态导入的别名

作为 alias() 方法的替代方法,每个查询 Bean 还提供一个静态 Alias 类,以备我们更愿意使用静态导入的情况。

例如,我们可以使用 QCustomer.Alias 来指定客户的属性,如下所示

List<Customer> customers =
  new QCustomer()

    .select(QCustomer.Alias.name, QCustomer.Alias.whenCreated)
    .findList();

然后,我们可以将它们更改为使用静态导入以获取

import static org.domain.query.QCustomer.Alias.name;
import static org.domain.query.QCustomer.Alias.whenCreated;
...


List<Customer> customers =
  new QCustomer()

    .select(name, whenCreated) // using static imports of QCustomer.Alias
    .findList();

像这样使用 Alias 的限制是,如果我们对多个查询 Bean 类型(如 QCustomer.Alias 和 QContact.Alias)执行此操作,那么我们可能会遇到名称冲突。例如,如果两者都有一个名为 whenCreated 的属性,我们只能静态导入其中一个。

import static ...query.QCustomer.Alias.name;
import static ...query.QCustomer.Alias.version;
import static ...query.QCustomer.Alias.whenCreated;
import static ...query.QContact.Alias.firstName;
import static ...query.QContact.Alias.lastName;

// Use explicit QContact.Alias.whenCreated (as clash with QCustomer.Alias.whenCreated)

List<Customer> customers =
  new QCustomer()
    .select(name, version, whenCreated)
    .contacts.fetch(firstName, lastName, QContact.Alias.whenCreated)

    .name.istartsWith("Rob")
    .findList();

公式

当我们想要指定公式时,需要使用此字符串选择子句。

// java
List<String> names =
  new QContact()
    .select("concat(lastName,', ',firstName)")
    .lastName.startsWith("A")
    .findSingleAttributeList();
// kotlin
var names: List<String> =
  QContact()
    .select("concat(lastName,' ',firstName)")
    .lastName.startsWith("A")
    .findSingleAttributeList()
示例 - Postgis ST_Distance 公式

在此示例中,我们使用公式末尾的 ::BigDecimal 转换显式转换为 Java BigDecimal 类型。

// given route is a Postgis geometry(linestring,4326)
// return the distance between the start and end points

BigDecimal routeDistance = query()
  .select("ST_Distance(ST_StartPoint(route), ST_EndPoint(route))::BigDecimal")
  .where()
  .idEq(tripId)
  .findSingleAttribute();

asDto

当我们使用选择公式时,有时我们希望将结果返回到普通的 DTO bean 中,而不是实体 bean。我们使用 .asDto(Class<D>) 将 ORM 查询转换为 DtoQuery。

有关更多详细信息,请参阅 DTO 查询

// ContactDto is a plain bean with email and fullName properties

List<ContactDto> contacts =
  new QContact()
    .select("email, concat(lastName, ', ', firstName) as fullName")
    .lastName.startsWith("A")
    .orderBy()
       .lastName.asc()
    .setMaxRows(10)
    .asDto(ContactDto.class)
    .findList();

Aggregation

与公式查询类似,我们可以在选择子句中使用 SUM、MAX、MIN、AVG 和 COUNT 的标准聚合。

有关更多详细信息,请参阅 聚合查询

单个聚合查询
// java
Timestamp maxWhen  =
  new QContact()
    .select("max(whenModified)")
    .findSingleAttribute()
// kotlin
var maxWhen: Timestamp =
  QContact()
    .select("max(whenModified)")
    .findSingleAttribute()
select max(t0.when_modified) from contact t0
按聚合查询分组

当使用多列聚合查询时,我们使用字符串选择子句。

List<MachineStats> result =
  new QMachineStats()
  .select("machine, date, max(rate)")
  .date.gt(LocalDate.now().minusDays(10))
  .query().having().gt("max(rate)", 4)
  .findList();

上述查询生成以下 sql

select t0.machine_id, t0.date, max(t0.rate)
from d_machine_stats t0
where t0.date > ?
group by t0.machine_id, t0.date
having max(t0.rate) > ?