2017-06-19 154 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

唉,无论如何,我的老板都喜欢最初的结果,所以我将其标记为已解决! –

相关问题