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

时间:2018-11-05 13:15:41

标签: java hibernate jpa jpql

我有一个使用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. 这是一个视图,仅用于检索最新数据

基类:

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

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

    ...

}

操作类:

@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;
    }

   ...
}

查看课程:

@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 {
}

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

1 个答案:

答案 0 :(得分:1)

FROMJOIN上的JPQL does not support子查询。仅在WHEREHAVING子句中。 Eclipse Link starting from 2.4支持FROM子句中的子查询。

every Criteria is converted to the JPQL一样,无法使用“标准”来做您想做的事。