#java #spring-data-jpa
#java #spring-data-jpa
Вопрос:
Предположим, что следующее:
public class Building {
@Column(nullable = false)
private String zipCode;
@OneToMany(mappedBy = "building", fetch = FetchType.LAZY)
private final Set<Contract> contracts = new HashSet<>();
}
public class Contract {
@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(nullable = false, updatable = false)
private Building building;
@Column(nullable = false)
private LocalDate activeFrom;
}
Используя предпочтительно репозитории spring-data-jpa, как я могу выбрать все здания с определенным zipCode
, а затем для каждого здания, все контракты с более activeFrom
ранним, чем X?
Все решения, которые я могу найти в Интернете, похоже, сосредоточены на фильтрации основного объекта ( Building
), тогда как я хотел бы использовать разные динамические критерии для дочернего объекта ( Contract
) и получать пустой список, если таковые не найдены. Я явно хочу получать здания без соответствующих контрактов.
Хорошо, если вместо классов сущностей используется DTO / projection.
Ответ №1:
Я исхожу из предположения, что вы ищете запрос JpaRepository, который вы могли бы использовать. Вы можете использовать «_» для применения запросов к полям во встроенных объектах.
Например, что-то вроде: findallbybuilding_zipcode и activefrombefore …
Комментарии:
1. Это отфильтровало
Building
бы s без aContract
, который активен до X. Я явно хочу, чтобы они возвращались с пустым списком в контрактах.2. Хорошо, извините, я не понял этого из вопроса. Я понял это как контракт, являющийся основным объектом, который вы хотите вернуть, следовательно, будет пустым, если ничего не найдено.
3. Аналогично, не уверен, как это можно сделать в формате метода, но, возможно, стоит использовать @Query с выборками Join.
Ответ №2:
Вы можете использовать что-то подобное для фильтрации по почтовому индексу и activeFrom
String FIND_ALL_BUILDINGS_BY_ZIP_CODE_AND_ACTIVE_FORM = "SELECT b FROM Building b"
" inner join b.contract as c "
" with c.activeFrom > :date "
" where b.zipCode = :zipCode";
@Query(FIND_ALL_BUILDINGS_BY_ZIP_CODE_AND_ACTIVE_FORM)
List<Group> findAllBuildingsByZipCodeAndActiveFrom(@Param("zipCode") String zipCode, @Param("date") LocalDate date);
Это даст вам пакет, который имеет по крайней мере один контракт, который активен с> даты
Также вы можете попробовать с этим запросом:
String FIND_ALL_BUILDINGS_BY_ZIP_CODE_AND_ACTIVE_FORM = "SELECT b FROM Building b"
" inner join b.contract as c "
" where c.activeFrom > :date "
" and b.zipCode = :zipCode";
Просто убедитесь, что вы присоединились ко второй таблице перед фильтрацией
Комментарии:
1.
This will give you a bulding that has atleast one contract that activeFrom > date
Я боюсь, что в этом проблема — я явно хочуBuildings
, чтобы соответствующие контракты тоже не возвращались.2. чем добавлять больше условий с помощью ИЛИ