Я создал приложение Spring Boot.Это REST-сервер.Поскольку сервисы REST используются клиентом Angular, в некоторых случаях у меня довольно большой запрос, в котором много LEFT и INNER JOIN для проверки необязательных полей поиска.
К сожалению, все поля поиска являются необязательными, поэтому JOINне всегда нужны.Прямо сейчас я использую репозиторий как это:
@RestResource(exported = false)
@Transactional(readOnly = true)
// @formatter:off
@Query("SELECT t FROM Ticket t " + "JOIN Account a ON a.username=t.createdBy "
+ "LEFT JOIN User u ON u.account=a "
+ "LEFT JOIN Customer c ON t.customer=c " + "LEFT JOIN Account ca ON c.account=ca " + "JOIN t.checkPoint ck "
+ "LEFT JOIN t.customer c1 " + "LEFT JOIN t.transitCertificate tc " + "WHERE "
+ "(:allFieldsSearch IS NULL OR (t.code LIKE CONCAT('%',:allFieldsSearch,'%') OR t.licensePlate1 LIKE CONCAT('%',:allFieldsSearch,'%') OR t.licensePlate2 LIKE CONCAT('%',:allFieldsSearch,'%') OR c.name LIKE CONCAT('%',:allFieldsSearch,'%') )) "
+ "AND (:code IS NULL OR t.code LIKE CONCAT('%',:code,'%')) "
+ "AND (:licensePlate IS NULL OR (t.licensePlate1 LIKE CONCAT(:licensePlate,'%') OR t.licensePlate2 LIKE CONCAT(:licensePlate,'%'))) "
+ "AND (:transitCertificate IS NULL OR tc.code=:transitCertificate) "
+ "AND (:customer IS NULL OR c1.name LIKE CONCAT('%',:customer,'%')) "
+ "AND (:checkPoint IS NULL OR ck.name LIKE CONCAT('%',:checkPoint,'%')) "
+ "AND (:agent IS NULL OR (a.type='USER' AND u.name LIKE CONCAT('%',:agent,'%')) OR (a.type='CUSTOMER' AND c.name LIKE CONCAT('%',:agent,'%'))) "
+ "AND (:paid IS NULL OR t.paid=:paid) " + "AND (:ecommerce IS NULL OR (:ecommerce=true AND t.salesChannel='ECOMMERCE')) "
+ "AND (:checkedMedia IS NULL OR (:checkedMedia=false AND t.checkedMedia=false AND medias > 0)) "
+ "AND (:checkedLicensePlate IS NULL OR (:checkedLicensePlate=false AND t.checkedLicensePlate=false AND ((t.engineEuroLevel1>3 OR (t.engineEuroLevel1=3 AND t.particulateFilter1=true)) OR (t.engineEuroLevel2>3 OR (t.engineEuroLevel2=3 AND t.particulateFilter2=true)))) ) "
+ "AND (:warning IS NULL OR (warning=:warning)) "
+ "AND (:color IS NULL OR (color=:color)) "
+ "AND (:status IS NULL OR t.status=:status) "
+ "AND (:from IS NULL OR t.entryDate>=:from) "
+ "AND (:until IS NULL OR t.entryDate<=:until) "
+ "AND (:fromCreatedDate IS NULL OR t.createdDate>=:fromCreatedDate) "
+ "AND (:untilCreatedDate IS NULL OR t.createdDate<=:untilCreatedDate) "
// the customer cannot see canceled tickets
+ "AND (CAST(t.status as string) <>?#{hasRole('ROLE_CUSTOMER') ? 'CANCELED':''}) "
+ "AND (ca.username=?#{principal.username} OR t.createdBy LIKE ?#{hasRole('ROLE_CUSTOMER') ? principal.username:'%'})")
// @formatter:on
public Page<Ticket> search(@Param("allFieldsSearch") String allFieldsSearch, @Param("code") String code,
@Param("licensePlate") String licensePlate, @Param("transitCertificate") String transitCertificate,
@Param("customer") String customer, @Param("agent") String agent, @Param("checkPoint") String checkPoint,
@Param("paid") Boolean paid, @Param("ecommerce") Boolean ecommerce, @Param("checkedMedia") Boolean checkedMedia,
@Param("checkedLicensePlate") Boolean checkedLicensePlate, @Param("warning") Boolean warning, @Param("color") String color,
@Param("status") TicketStatus status, @Param("from") Instant from, @Param("until") Instant until,
@Param("fromCreatedDate") Instant fromCreatedDate, @Param("untilCreatedDate") Instant untilCreatedDate, Pageable pageable);
Код довольно удобен.Он компактен и больше ничего не нужно.К сожалению, здесь я делаю все JOIN, даже если пользователь не устанавливает никаких параметров.
Мне было интересно, есть ли способ создания условного JOIN на основе наличия параметра.