Spring JPQL用于字符串数组作为可选参数

时间:2018-06-26 17:32:18

标签: java sql spring jpa jpql

我创建了一个具有端点GET的REST API,该端点应返回与给定条件匹配的邮件。 GET端点的所有参数都是可选的,应由AND串联:

  1. id:邮件的ID(在创建新邮件时自动生成)
  2. mail_from:邮件的发件人
  3. received_before:过滤给定日期之前收到的邮件
  4. received_after:过滤给定日期之后收到的邮件
  5. rcpt_to:收件人的邮件地址数组;重要的是,过滤后的邮件应包含作为参数值rcpt_to
  6. 给出的所有收件人

由于我无法使用Spring docs中描述的方法名称通过查询创建按日期范围进行过滤,因此我创建了自定义查询。

我实现了对参数1-4的查询(请参见方法getMailByCustomQuery)和对参数rcpt_to的另一个查询(请参见方法getMailByRecipient)。由于后者使用HAVING,因此我不能简单地合并两个查询。如何合并两个查询,以使GET端点具有单个方法/查询?还是有其他替代方法?

MailRepository.java

@RepositoryRestResource
public interface MailRepository extends JpaRepository<Mail, Long> {
    @Query("SELECT m FROM Mail m " +
            "WHERE (:id IS NULL OR m.id = :id) " +
            "AND (:mailFrom IS NULL OR m.mailFrom = :mailFrom)" +
            "AND ( CAST(:receivedBefore AS date) IS NULL OR m.received < :receivedBefore) " +
            "AND ( CAST(:receivedAfter AS date) IS NULL OR m.received > :receivedAfter)")
    List<Mail> getMailByCustomQuery(
            @Param("id") Long id,
            @Param("mailFrom") String mailFrom,
            @Param("receivedBefore") Date receivedBefore,
            @Param("receivedAfter") Date receivedAfter
    );

    @Query("SELECT m " +
            "FROM Mail m LEFT JOIN m.rcptTo to2 " +
            "WHERE to2 IN :rcptTo " +
            "GROUP BY m.id " +
            "HAVING COUNT(DISTINCT to2) = :rcptToLength")
    List<Mail> getMailByRecipient(
            @Param("rcptTo") List<String> rcptTo,
            @Param("rcptToLength") Long rcptToLength
    );
}

MailRestController.java

@RestController
@RequestMapping("/mailStore")
public class MailRestController {
private MailRepository repository;
@Inject
public void setRepository(MailRepository repository) {
    this.repository = repository;
}

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<?> addMail(@RequestBody Mail mail) {
    return new ResponseEntity<>(repository.save(mail), HttpStatus.CREATED);
}

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Collection<Mail>> getMail(
        @RequestParam(required = false) Long id,
        // Example for timestamp format: 2001-07-22T12:08:56.235-07:00
        @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX") Date received_before,
        @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX") Date received_after,
        @RequestParam(required = false) String mail_from) {
    return new ResponseEntity<>(repository.getMailByCustomQuery(id, mail_from, received_before, received_after), HttpStatus.OK);
}

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Collection<Mail>> getMail(
        @RequestParam(required = false) List<String> rcpt_to) {
    return new ResponseEntity<>(repository.getMailByRecipient(rcpt_to, (long) rcpt_to.size()), HttpStatus.OK);
}

}

Mail.java (省略了getter和setter)

@Entity
@EnableAutoConfiguration
public class Mail {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @JsonProperty("id")
    private Long id;

    @Column(name = "received")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
    @Temporal(TemporalType.TIMESTAMP)
    @JsonProperty("received")
    private Date received;

    @JsonProperty("received_from")
    private String receivedFrom;

    @JsonProperty("received_by")
    private String receivedBy;

    @JsonProperty("mail_from")
    private String mailFrom;

    @JsonProperty("data")
    private String data;

    @ElementCollection(fetch = FetchType.EAGER, targetClass = String.class)
    @CollectionTable(name = "rcptTo")
    @Column(name = "Value")
    @JsonProperty("rcpt_to")
    private List<String> rcptTo = new ArrayList<>();

public Mail(Date received, String receivedFrom, String receivedBy, String mailFrom,
            List<String> rcptTo, String data) {
    this.received = received;
    this.receivedFrom = receivedFrom;
    this.receivedBy = receivedBy;
    this.mailFrom = mailFrom;
    this.rcptTo = rcptTo;
    this.data = data;
}

0 个答案:

没有答案