JPA CriteriaQuery 查询每个实体的最新数据

JPA CriteriaQuery Query latest data of each entity

我有一个项目使用SpringBoot 1.5.9(无法更改版本)。

我有这些实体:

@Entity
@Table(name = "data")
public class DataEntity extends Timestampable {

    @Column(name = "value")
    private String value;

    @Column(name = "data_timestamp")
    private ZonedDateTime dataTimestamp;

    @ManyToOne
    @JoinColumn
    private DataTypeEntity type;

    @ManyToOne
    @JoinColumn
    private AssetEntity asset;
}

@Entity
@Table(name = "data_type")
public class DataTypeEntity extends Timestampable {

    @Column(name = "name", unique = true)
    private String name;

    ...
}

我有这个有效的 SQL 查询(在 PostgreSQL 下),以检索每项资产的最新数据 (source):

SELECT * FROM data d1
JOIN (
  SELECT max(data_timestamp) as newest, asset_id FROM data
  GROUP BY asset_id
) d2
ON d1.data_timestamp = d2.newest AND d1.asset_id = d2.asset_id
WHERE d1.type_id IN (
  SELECT id FROM data_type
  WHERE name = 'ELECTRICITY_CONSUMPTION'
);

我想将此查询转换为 JPA CriteriaQuery。 有没有办法这样做,或者我是否需要在特定实体上使用 @SubSelect 注释?

感谢阅读本文!

(丑陋)解决方案

我最终使用了带有 SubSelect 的数据库视图。 我已将我的 DataEntity 拆分为 2 个实体:

  1. 一个操作数据
  2. 另一个视图,仅用于检索最新数据

基地 class :

@MappedSuperclass
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractDataEntity extends Timestampable {

    @Column(name = "value")
    protected String value;

    ...

}

操纵class:

@Entity
@SequenceGenerator(name = "idgen", sequenceName = "data_seq")
@Table(name = "data")
@DiscriminatorValue("DataEntity")
public class DataEntity extends AbstractDataEntity {
    @Override
    public DataEntity setValue(String value) {
        super.setValue(value);
        return this;
    }

   ...
}

查看class:

@Entity
@Immutable
@SequenceGenerator(name = "idgen", sequenceName = "view_data_last_seq")
@DiscriminatorValue("LastDataView")
@Subselect(
    "SELECT * FROM data d1 " +
    "JOIN ( " +
    "  SELECT max(d.data_timestamp) as newest, d.asset_id, d.type_id FROM data d " +
    "  WHERE d.parameter_id IS NULL " +
    "  GROUP BY d.asset_id, d.type_id" +
    ") d2 " +
    "ON d1.data_timestamp = d2.newest " +
    "  AND d1.asset_id = d2.asset_id " +
    "  AND d1.type_id = d2.type_id"
)
public class LastDataView extends AbstractDataEntity {
}

即使我觉得这个解决方案很丑陋,它也可能对其他人有所帮助!

JPQL does not support subqueries on FROM or JOIN. Only in WHERE or HAVING clauses. Eclipse Link, starting from 2.4,支持 FROM 子句上的子查询。

作为 every Criteria is converted to the JPQL,无法使用 Criteria 执行您想要的操作。