在版本字段上过滤实体我有一个包含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);
}
};
}
非常感谢您的帮助和建议!