У меня есть объект со встроенным идентификатором, который содержит поле id и version.Фильтрация объектов в поле версии с помощью JPA Критерии-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() {}
}
Мне нужно запросить базу данных с некоторыми критериями в качестве фильтра для объекта. Например, я запрошу с датой и списком идентификаторов.
List<MyEntity> listEntities = getMyEntities(List<Long> ids, DateTime date);
мне удалось создать запрос, который retreives все объекты, для которых их идентификатор в списке идентификаторов и что при условии, дата между свойствами «начать» и «конец» дата в MyEntity.
Но поскольку этот объект имеет составной идентификатор, существует много MyEntity с тем же «id», который может соответствовать параметрам запроса. Я хочу добавить еще один фильтр, чтобы восстановить MyEntity с самым высоким номером «версии», если их много с одним и тем же «id».
Вот пример того, что может быть в базе данных:
+------+-----------+--------------------+
| id | version | began | end |
+------+-----------+--------------------+
| 1 | 1 | ... | ... |
| 1 | 2 | ... | ... |
| 1 | 3 | ... | ... |
| 2 | 1 | ... | ... |
| 2 | 2 | ... | ... |
+------+-----------+--------------------+
Если все предыдущие записи базы данных соответствуют параметрам фильтрации, мне нужно только получить эти один, потому что они являются те, с самой высокой версией номер для их соответствующего идентификатору:
+------+-----------+--------------------+
| id | version | began | end |
+------+-----------+--------------------+
| 1 | 3 | ... | ... |
| 2 | 2 | ... | ... |
+------+-----------+--------------------+
в настоящее время я делаю запрос, но я фильтровать версию внутри метода внутри моей службы, но я предпочел бы, если версия уже фильтруется в запросе к базе данных. Мне не нужно возвращать записи, которые будут отброшены после фильтрации.
Я ищу способ самостоятельно объединиться с API-критериями JPA.
В следующей ссылке кажется, что принятый ответ разрешит мою проблему, я задаюсь вопросом, как я буду переводить предложенный SQL в API-критерии JPA.
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. Это способ сделать самообслуживание с API-интерфейсом JPA?
Возможно, есть еще один способ для создания моего запроса, чем с самостоятельным левым соединением, как это предлагается в другом вопросе stackoverflow.
Я использую спецификацию Spring Data JPA для построения моего запроса с помощью Predicate. Затем используется findAll (спецификация). У меня уже есть два других метода спецификации для генерации предиката для forIds() и 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);
}
};
}
Большое спасибо за вашу помощь и предложение!