【发布时间】:2018-11-17 14:40:52
【问题描述】:
我创建了一个 Spring Boot 应用程序。它是一个 REST 服务器。 因为 Angular 客户端使用 REST 服务,所以在某些视图中,我有一个相当大的查询,其中我有很多 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。
【问题讨论】:
标签: spring spring-boot spring-data-jpa