在版本字段上過濾實體我有一個包含id和version字段的嵌入id的實體。使用JPA Criteria-API
@Entity
@Table(name = "MyEntity")
public class MyEntity {
@EmbeddedId
private MyEntityEmbeddedId compositeId;
@Column
private DateTime begin;
@Column
private DateTime end;
}
@Embeddable
public class MyEntityEmbeddedId {
@Column(name = "ID", nullable = false, updatable = false)
private Long id;
@Column(name = "VERSION", nullable = false, updatable = false)
private Long version;
public MyEntityEmbeddedId() {}
}
我需要用一些標準來查詢數據庫作爲實體的過濾器。例如,我會請求一個日期和ID列表。
List<MyEntity> listEntities = getMyEntities(List<Long> ids, DateTime date);
我成功創建該retreives所有實體,他們的ID是在IDS列表所提供的日期是myEntity所的「開始」和「結束」日期屬性之間的查詢。
但是由於這個實體有一個複合id,所以有許多MyEntity具有相同的「id」,可以對應請求參數。我想添加另一個過濾器來檢索具有最高「版本」號碼的MyEntity,如果有許多具有相同的「ID」。
這裏是什麼可能是數據庫中的一個例子:
+------+-----------+--------------------+
| id | version | began | end |
+------+-----------+--------------------+
| 1 | 1 | ... | ... |
| 1 | 2 | ... | ... |
| 1 | 3 | ... | ... |
| 2 | 1 | ... | ... |
| 2 | 2 | ... | ... |
+------+-----------+--------------------+
如果以前所有的數據庫記錄對應的過濾參數,我只需要得到這些之一,因爲他們是那些擁有最高版本他們的對應ID編號:
+------+-----------+--------------------+
| id | version | began | end |
+------+-----------+--------------------+
| 1 | 3 | ... | ... |
| 2 | 2 | ... | ... |
+------+-----------+--------------------+
目前,我的要求去做,但我過濾我的服務中的方法中的版本,但我寧願它如果版本是在數據庫請求已經過濾。我不需要檢索在過濾版本後將被丟棄的記錄。
我正在尋找一種方法來使用JPA Criteria-API進行自我連接。
在下面的鏈接中,似乎接受的答案將解決我的問題,我想知道如何在JPA Criteria-API中翻譯建議的SQL。
SQL Select only rows with Max Value on a Column
select yt1.*
from yourtable yt1
left outer join yourtable yt2
on (yt1.id = yt2.id and yt1.rev < yt2.rev)
where yt2.id is null;
我的問題是,當我試圖創建的連接。您需要提供鏈接到第二個實體的第一個實體的屬性。由於我想進行自我連接,因此實體內部沒有指向自身的屬性。
Join<MyEntity, MyEntity> selfJoin = root.join(MyEntity_.???);
正如您所看到的,我使用的是MyEntity的靜態元模型。有沒有辦法使用JPA Criteria-API進行自我加入?
或者,也許有另一種方法來建立我的請求,而不是像其他stackoverflow問題中建議的自連接。
我正在使用Spring Data JPA Specification來構建帶有謂詞的查詢。然後使用findAll(Specification)。我已經有兩個規範方法爲withIds()和withDate()生成謂詞。這使我可以用用戶提供的「未定數量」參數創建查詢。
public static Specification<MyEntity> withIdAndDate(final List<Long> ids,
final DateTime date) {
return new Specification<MyEntity>() {
@Override
public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query,
CriteriaBuilder cb){
Join<MyEntity, MyEntity> selfJoin = root.join();
Predicate pIds = withIds(ids).toPredicate(root, query, cb);
Predicate pDate = withDate(date).toPredicate(root, query, cb);
return cb.and(pIds, pDate);
}
};
}
非常感謝您的幫助和建議!