2017-06-19 155 views
1

因此,我有一個可以工作的jpa數據庫查詢,並從該表中返回所有SiteBmdfBusinessDay,並通過加入他們的ID列將它們與其相應的SiteBmdf關聯起來。我想要做的是,而不是讓所有的SiteBmdfBusinessDay的,我只想得到與最近的businessDay的。JPA只選擇每個項目的最近日期

這裏是SiteBmdfBusinessDay類...

@Entity 
public class SiteBmdfBusinessDay extends BaseEntity { 

private static final long serialVersionUID = 1L; 

private Long id; 
private SiteBmdf siteBmdf; 
private DateTime businessDay; 
private Long failedCount; 
private DateTime lastSuccessfulBusinessDay; 
private DateTime lastSuccessfulFullBusinessDay; 
private Ticket ticket; 

@Id 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "site_bmdf_business_day_site_bmdf_business_day_id_seq") 
@SequenceGenerator(name = "site_bmdf_business_day_site_bmdf_business_day_id_seq", sequenceName = "site_bmdf_business_day_site_bmdf_business_day_id_seq", allocationSize = 1) 
@Column(name = "site_bmdf_business_day_id") 
public Long getId() { 
    return id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

@ManyToOne 
@JoinColumn(name = "site_bmdf_id") 
public SiteBmdf getSiteBmdf() { 
    return siteBmdf; 
} 

public void setSiteBmdf(SiteBmdf siteBmdf) { 
    this.siteBmdf = siteBmdf; 
} 

@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime", parameters = { 
     @Parameter(name = "databaseZone", value = "UTC"), @Parameter(name = "javaZone", value = "UTC") }) 
public DateTime getBusinessDay() { 
    return businessDay; 
} 

public void setBusinessDay(DateTime businessDay) { 
    this.businessDay = businessDay; 
} 

public Long getFailedCount() { 
    return failedCount; 
} 

public void setFailedCount(Long count) { 
    this.failedCount = count; 
} 

@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime", parameters = { 
     @Parameter(name = "databaseZone", value = "UTC"), @Parameter(name = "javaZone", value = "UTC") }) 
public DateTime getLastSuccessfulBusinessDay() { 
    return lastSuccessfulBusinessDay; 
} 

public void setLastSuccessfulBusinessDay(DateTime lastSuccessfulBusinessDay) { 
    this.lastSuccessfulBusinessDay = lastSuccessfulBusinessDay; 
} 

@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime", parameters = { 
     @Parameter(name = "databaseZone", value = "UTC"), @Parameter(name = "javaZone", value = "UTC") }) 
public DateTime getLastSuccessfulFullBusinessDay() { 
    return lastSuccessfulFullBusinessDay; 
} 

public void setLastSuccessfulFullBusinessDay(DateTime lastSuccessfulFullBusinessDay) { 
    this.lastSuccessfulFullBusinessDay = lastSuccessfulFullBusinessDay; 
} 

@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
@JoinColumn(name = "ticket_id") 
public Ticket getTicket() { 
    return ticket; 
} 

public void setTicket(Ticket ticket) { 
    this.ticket = ticket; 
} 
} 

而且SiteBmdf類...

@Entity 
public class SiteBmdf extends BaseEntity { 

private static final long serialVersionUID = 1L; 

private Long id; 
private String site; 
private Long failureCount; 
private Set<SiteBmdfBusinessDay> businessDays; 
private List<SiteBmdfNote> notes; 
private Resolution resolution; 

@Id 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "site_bmdf_site_bmdf_id_seq") 
@SequenceGenerator(name = "site_bmdf_site_bmdf_id_seq", sequenceName = "site_bmdf_site_bmdf_id_seq", allocationSize = 1) 
@Column(name = "site_bmdf_id") 
public Long getId() { 
    return id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

public String getSite() { 
    return site; 
} 

public void setSite(String site) { 
    this.site = site; 
} 

@Transient 
public Long getFailureCount() { 
    return failureCount; 
} 

public void setFailureCount(Long failureCount) { 
    this.failureCount = failureCount; 
} 

@JsonIgnore 
@OneToMany(mappedBy = "siteBmdf", orphanRemoval = true, cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
public Set<SiteBmdfBusinessDay> getBusinessDays() { 
    return this.businessDays; 
} 

public void setBusinessDays(Set<SiteBmdfBusinessDay> businessDays) { 
    this.businessDays = businessDays; 
} 

@OneToMany(mappedBy = "siteBmdf", orphanRemoval = true, cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
public List<SiteBmdfNote> getNotes() { 
    Collections.sort(notes); 
    return notes; 
} 

public void setNotes(List<SiteBmdfNote> notes) { 
    this.notes = notes; 
} 

@ManyToOne 
@JoinColumn(name = "resolutionId") 
public Resolution getResolution() { 
    return resolution; 
} 

public void setResolution(Resolution resolution) { 
    this.resolution = resolution; 
} 
} 

這裏是當前的查詢方法....

@Override 
public PageImpl<SiteBmdfBusinessDay> bmdfSitePaged(UiBuildCriteria criteria) { 

    CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
    CriteriaQuery<SiteBmdfBusinessDay> query = builder.createQuery(SiteBmdfBusinessDay.class); 
    Root<SiteBmdfBusinessDay> root = query.from(SiteBmdfBusinessDay.class); 

    if (!criteria.getSearch().getPredicateObject().isEmpty()) { 
     List<Predicate> predicates = predicateBuilderService.buildPredicates(builder, root, criteria.getSearch()); 
     query.where(builder.and(predicates.toArray(new Predicate[] {}))); 
    } 

    query.select(root); 

    builder.max(root.<Long>get("businessDay")); 

    // get the count for PageImpl 
    Long total = this.count(criteria); 

    // Set the order by 
    List<CustomSort> defaultSorts = new ArrayList<CustomSort>(
      Arrays.asList(
       new CustomSort("businessDay", Boolean.TRUE), 
       new CustomSort("siteBmdf.site", Boolean.FALSE) 
      )); 

    List<Order> orders = sortOrderBuilderService.buildSort(builder, root, criteria.getSort(), defaultSorts); 

    query.orderBy(orders); 

    List<SiteBmdfBusinessDay> content = entityManager.createQuery(query).setFirstResult(criteria.getPagination().getStart()) 
      .setMaxResults(criteria.getPagination().getNumber()).getResultList(); 

    return new PageImpl<>(content, criteria.getPageRequest(), total); 
} 

就像我說的那樣,當前結果只是SiteBmdfBusinessDay表中的所有項目及其相應的站點Bmdfs。我只想爲每個網站提供最近一次營業日的SiteBmdfBusinessDays。

舉例來說,如果我有表site_bmdf_business_day:

site_bmdf_business_day_id | site_bmdf_id | business_day 
1       | 1   | 6/1/2011 
2       | 2   | 6/1/2011 
3       | 1   | 6/6/2011 
4       | 3   | 6/6/2011 

我只想顯示:

site_bmdf_business_day_id | site_bmdf_id | business_day 
2       | 2   | 6/1/2011 
3       | 1   | 6/6/2011 
4       | 3   | 6/6/2011 

我知道我將需要沿着builder.max東西線(根.get(「businessDay」))但我不知道如何實現它。

在這裏的任何幫助將不勝感激。

請注意,this question是類似的,但不是我正在尋找的所有答案都在SQL中,我需要在jpa這裏的東西。

回答

1

對於這些類型的查詢,我通常將其歸結爲sql(沒有分頁和其他限制),然後將其構建到查詢構建器中。它使更清潔的代碼IMO。你正在尋找的是類似於

select a.* from SiteBmdfBusinessDay a 
inner join 
(select site_bmdf_id, max (business_day) as business_day 
    from SiteBmdfBusinessDay group by site_bmdf_id) b 
on (a.site_bmdf_id = b.site_bmdf_id) and (a.business_day = b.business_day) 

這假設每天最多有一個條目,每個site_bmdf_id。

就我所知,這是不可行的,但是,你可以把它作爲一個創建查詢,它工作得很好(因爲結果只是一個普通的實體)。但是,這是一個非常性能過高的查詢,假設你有一個體面的數據量。除非你有一個小的數據集,否則最好是把它全部,然後以編程方式過濾出重複項(你應該可以在O(n)時間內完成)。

+0

那麼,SQL絕對有效,所以謝謝你爲此!儘管如此,我不打算將此標記爲已解決,以防任何人有一個作爲建造者的想法,這正是我真正需要的。這裏的事情是,雖然這個特定的數據集可能不會太大,但我想在表格可能接近1M行的地方使用此實現,所以我絕對無法拉動整個集合並解析它。 –

+0

唉,無論如何,我的老闆都喜歡最初的結果,所以我將其標記爲已解決! –

相關問題