微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 JPA Criteria Queries 和 Spring Data Specification 将子查询链接到主查询?

如何解决如何使用 JPA Criteria Queries 和 Spring Data Specification 将子查询链接到主查询?

我有这三个实体:

@Entity
@Table(name="documento")
public class Documento extends AbstractAuditableActivationEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id_documento",unique=true,nullable=false)
    private Long id;

...
...

    @OnetoMany(fetch=FetchType.LAZY,orphanRemoval=true,cascade=CascadeType.ALL,mappedBy="documento")
    private List<DocumentoEvent> events;

...
...
}
@Entity
@Table(name = "documento_event")
public class DocumentoEvent extends AbstractBpmnEvent {

    private static final long serialVersionUID = 1177989257158109761L;
    
    @Id
    @Getter
    @Setter
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id_documento_event",nullable=false)
    private Long id;
    
    @Getter
    @Setter
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="id_documento",nullable = false)
    private Documento documento;

}

@MappedSuperclass
public abstract class AbstractBpmnEvent implements Serializable {
    private static final long serialVersionUID = 6718273240496032533L;

...
...

    @Column(name = "bpm_task_end_time")
    @Temporal(TemporalType.TIMESTAMP)
    private Date bpmtaskEndTime;
    
    @Column(name = "bpm_task_status",length = FieldsLength.EVENT_TYPE)
    private String bpmtaskStatus;

...
...
}

我想要的是动态构建这样的查询

SELECT d.id_documento 
FROM documento d join documento_event de on d.id_documento = de.id_documento 
WHERE de.bpm_task_status = ? AND de.bpm_task_end_time is not null AND de.bpm_task_end_time = (
    SELECT max(bpm_task_end_time)
    FROM documento_event de2
    WHERE de2.id_documento = d.id_documento
)

使用 JPA 标准查询和 Spring 规范。 这就是我想要做的:

private List<Predicate> getPredicateRegistrodocumento(
            final DocumentoFilters filters,final Root<Documento> documento,final CriteriaBuilder cb,final CriteriaQuery<?> query) {

List<Predicate> predicates = new ArrayList<Predicate>();

...
...

if(CollectionUtils.isNotEmpty(filters.getWorkflowStatusCodes())) {
            predicates.add(
                    cb.and(
                            documento.join(Documento_.EVENTS).get(AbstractBpmnEvent_.BPM_TASK_STATUS).in(filters.getWorkflowStatusCodes()),cb.isNotNull(documento.join(Documento_.EVENTS).get(AbstractBpmnEvent_.BPM_TASK_END_TIME))
                            cb.equal(documento.join(Documento_.EVENTS).get(AbstractBpmnEvent_.BPM_TASK_END_TIME),latestEvent(query,cb,documento))
                    )
            );
        }
...
...

return predicates;

}

private Subquery<Date> latestEvent(final CriteriaQuery<?> query,final CriteriaBuilder cb){

        Subquery<Date> subquery = query.subquery(Date.class);
        Root<DocumentoEvent> documentoEvent = subquery.from(DocumentoEvent.class);
        subquery.select(cb.greatest(documentoEvent.get(DocumentoEvent_.BPM_TASK_END_TIME))
        );

        return subquery;
    }

我觉得我已经很接近了,但还没有完全到位,因为该子查询的作用是获取所有 MAX(bpm_task_end_time) 中的 documento_event,而不仅仅是 documento_event.id_documento 等于 { 的行的 documento.id_documento {1}} 的主查询

我该怎么做?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。