2014-06-13 1 views
0

JPA/JPQL 및 최대 절전 모드를 사용하여 항목을 인용 할 수있는 엔티티가 몇 개 있습니다.JPQL 조인으로 결과를 두 배로 만드는 방법이 없습니다.

견적에는 많은 견적 항목이 있으며 각 항목에는 0 개 이상의 조정 사항이있을 수 있습니다. 각각의 조정은 할인 또는 할증료이며, 백분율 (즉, 항목의 가격 비율) 또는 금액 (즉, 고정 값)입니다.

저에게 가치를 줄 수있는 JPQL 쿼리를 작성하려고합니다. 주어진 지역 및 사용자 및 시간 기간에 대한 모든 견적을 인용 부호에 대한 각 견적 항목의 가격과 조정 값을 합산합니다. 나는 거의 일하고 있지만 그것이 옳지 않다.

String query = "select q.user, q.contact.parent.region, sum(case " + 
     " when a.type = :type_surcharge and a.amountType = :amount_type_percentage then (a.amount * qi.price) " + 
     " when a.type = :type_surcharge and a.amountType = :amount_type_amount then (a.amount) " + 
     " when a.type = :type_discount and a.amountType = :amount_type_percentage then (-1 * a.amount * qi.price) " + 
     " else (-1 * a.amount) end) + sum(qi.price) " + 
     " from " + Quote.class.getName() + " q " + 
     " left join q.quoteItems qi " + 
     " left join qi.adjustments a " + 
     " where q.date between :from and :to and q.contact.parent.region in :regions group by q.user, q.contact.parent.region"; 

문제는 견적 항목이 하나 이상의 조정이있는 경우, 그 항목이

사람이 쿼리에 수정을 도와 수

합 (qi.price) 계산에 여러 번 나타나는 것입니다 각 견적 항목을 합계에 한 번만 포함 시키려면? ( sum(distinct qi.price) 작동하지 않습니다) 가능하면 단일 쿼리에서 수행 할 수 있기를 바래요.

편집 : 내가 생각했던 것보다 더 잘못되었습니다. 왼쪽 조인 (?)을 사용하고 있어도 조정하지 않고 따옴표가 있으면 합계 값에 대해 쿼리가 null을 반환합니다. 데이터가 올바른 경우는 다음과 같습니다. - 항목에 대해 0 또는 1 조정이 있습니다. - 지역/사용자/기간 필터를 통과하는 모든 따옴표에 하나 이상의 항목에 대한 조정이 있습니다.

엔티티 (간체)

@Entity 
@DiscriminatorValue(AbstractCollateral.TYPE_QUOTE) 
@Table(name="customer_quote", uniqueConstraints={@UniqueConstraint(name="quote_number_uk", columnNames={"number"})}) 
public class Quote extends AbstractCollateral<QuotedCarePack> 
{ 
    ... other elements 

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval=true) 
    protected Set<QuotedCarePack> quoteItems; 

} 

@Entity 
@Inheritance(strategy=InheritanceType.JOINED) 
@DiscriminatorColumn(name="collateral_type", discriminatorType=DiscriminatorType.STRING, length=10) 
@Table(name="abstract_collateral") 
public abstract class AbstractCollateral<T extends AbstractCollateralItem<?>> extends AbstractManagedData implements ContactInfo{ 

    private static final long serialVersionUID = 1L; 

    public static final String TYPE_ORDER = "order"; 
    public static final String TYPE_QUOTE = "quote"; 

    @Column(name="collateral_type", insertable=true, updatable=false, length=10) 
    protected String collateralType; 

    @ManyToOne(fetch=FetchType.EAGER) 
    @JoinColumn(name="customer_contact_id", nullable=false) 
    protected CustomerContact contact; 

    @ManyToOne(fetch=FetchType.EAGER) 
    @JoinColumn(name="user_id", nullable=false) 
    protected User user; 
    /** 
    * The date the collateral was made (not the sent date, necessarily) 
    */ 
    @Column(name="creation_date", nullable=false) 
    @Temporal(TemporalType.TIMESTAMP) 
    protected Date date; 
} 

@Entity(name="quoted_care_pack") 
public class QuotedCarePack extends AbstractCollateralItem<Quote> { 

    private static final long serialVersionUID = 1L; 

    @ManyToOne(fetch=FetchType.EAGER) 
    @JoinColumn(name="quote_id", nullable=false) 
    protected Quote parent; 

    @OneToMany(fetch=FetchType.EAGER, cascade={CascadeType.PERSIST, CascadeType.MERGE}) 
    @JoinTable 
    (
     name="quoted_care_pack_adjustment", 
     joinColumns={ @JoinColumn(name="quoted_care_pack_id", referencedColumnName="id") }, 
     inverseJoinColumns={ @JoinColumn(name="adjustment_id", referencedColumnName="id", unique=true) } 
) 
    protected Set<Adjustment> adjustments; 
} 

@Entity(name="adjustment") 
public class Adjustment extends AbstractManagedData { 

    private static final long serialVersionUID = 1L; 

    @Column(name="amount") 
    protected double amount; 
    @Column(name="reason", length=100) 
    protected String reason; 
    @Column(name="type") 
    @Enumerated(EnumType.STRING) 
    protected AdjustmentType type; 
    @Column(name="amount_type") 
    @Enumerated(EnumType.STRING) 
    protected AdjustmentAmountType amountType; 
} 

답변

1

불행하게도, JPA는 그래서는 영향을주지 않습니다 모든 조정의 합계를 얻기 위해 조인해야 할 것입니다 select 절에 서브 쿼리를 지원하지 않습니다 quoteItems의 합계입니다.

이 두 쿼리 네이티브 SQL을 사용하거나 실행 잎 - 조정 합에 대한 qi.price에 대한 합계 다른 하나 :

"select q.user, q.contact.parent.region, sum(qi.price) " + 
     " from " + Quote.class.getName() + " q " + 
     " left join q.quoteItems qi " + 
     " where q.date between :from and :to and q.contact.parent.region in :regions group by q.user, q.contact.parent.region"; 

"select q.user, q.contact.parent.region, sum(case " + 
     " when a.type = :type_surcharge and a.amountType = :amount_type_percentage then (a.amount * qi.price) " + 
     " when a.type = :type_surcharge and a.amountType = :amount_type_amount then (a.amount) " + 
     " when a.type = :type_discount and a.amountType = :amount_type_percentage then (-1 * a.amount * qi.price) " + 
     " else (-1 * a.amount) end) " + 
     " from " + Quote.class.getName() + " q " + 
     " left join q.quoteItems qi " + 
     " left join qi.adjustments a " + 
     " where q.date between :from and :to and q.contact.parent.region in :regions group by q.user, q.contact.parent.region"; 
+0

감사 크리스! 부끄러운 일이지만 한 가지 쿼리로 수행 할 수는 없지만 제대로 작동합니다. – fancyplants

관련 문제