简体   繁体   中英

JPA CriteriaQuery Query latest data of each entity

I have a project that uses SpringBoot 1.5.9 (can't change version).

I have these entities :

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

    ...
}

I have this working SQL query (under PostgreSQL), to retrieve the latest data per asset ( 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'
);

I want to translate this query into a JPA CriteriaQuery. Is there a way to do so, or do I need to use a @SubSelect annotation on a specific entity ?

Thanks for reading this !

(UGLY) SOLUTION

I ended up using a database View, with a SubSelect. I've split my DataEntity into 2 entities :

  1. One to manipulate the datas
  2. Anoher that is a view and used only to retrieve the latest data

Base class :

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

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

    ...

}

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

   ...
}

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

Even if I find this solution ugly, it may help others !

JPQL does not support subqueries on FROM or JOIN . Only in WHERE or HAVING clauses. Eclipse Link, starting from 2.4 , have support for subqueries on the FROM clause.

As every Criteria is converted to the JPQL , it's not possible to use Criteria to do what you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM