2012-07-16 185 views
0

我有一個實體休眠標準

public class CommissionSummary {  
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 
    @Column(length = 100) 
    private String advisorCode; 
    @Column(length = 100) 
    private String advisorName; 
    private String advisorCodeParent; 
    @Column(length = 100) 
    private String advisorNameParent; 
    @Column(length = 100) 
    private String advisorPost; 
    @Column 
    private Double percentage; 
    @Column 
    private Double diffPercentage; 
    @Column 
    private Double saleAmount; 
    @Column 
    private Long saleCount; 
    @Column 
    **private Double commissionAmount; 
    @Column 
    private Integer month; 
    @Column 
    private Integer year;** 
    //Getter Setter 
} 

在屏幕上用戶正在輸入的標準來獲取2個日期之間的日期。

Ex。 2012年1月1日至2012年7月30日

在CommissionSummary實體中沒有日期列,但它有月份和年份2個單獨的列。

我想根據月份和年份欄獲取用戶給出的從日期到日期的CommissionSummary記錄。

那麼如何使用Hibernate Criteria/Restrictions來實現這個?

注意:日期字段對於從當前輸入的用戶沒有任何意義。

回答

3

可以打破標準分解成三個較小的標準脫節:

  1. 該委員會的年度等於查詢的開始年份,其月份大於或等於查詢的起始月份
  2. 佣金的年份大於查詢的開始年份並且小於其結束年份
  3. 該委員會的年度等於查詢的NEND年,其每月小於或等於查詢的月末

你可以寫的每一個作爲兩個簡單比較的結合的。這看起來像(未測試!):

int fromYear, fromMonth, toYear, toMonth; 
Property year = Property.forName("year"); 
Property month = Property.forName("month"); 
session.createCriteria(CommissionSummary.class).add(Restrictions.disjunction() 
    .add(Restrictions.and(year.eq(fromYear), month.ge(fromMonth)) 
    .add(Restrictions.and(year.gt(fromYear), year.lt(toYear)) 
    .add(Restrictions.and(year.eq(toYear), month.le(toMonth)) 
); 
+0

它的工作原理,只需很少的Syntaxchanges是必需的。這裏是生成的SQL:SELECT this _。* FROM Commissionsummary this_ WHERE((this_.year = 2011 AND this_.month> = 11)OR(this_.year> 2011 AND this_.year <2012)OR(this_.year = 2012 AND this_.month <= 2)) – 2012-07-17 04:51:06

-1

您可以使用HQL來選擇你想要什麼:

session.beginTransaction(); 
session.clear(); 

Query query = session.createSQLQuery(" from CommissionSummary CS where to_date(CS.year || '-' || CS.month || '-01', 'YYYY-MM-DD') between :startDate and :endDate)" 

List result = query.list(); 
+0

-1:那不回答問題。 OP要求從一個日期到另一個日期的所有記錄。 – 2012-07-16 09:22:56

+0

我在仔細閱讀問題後糾正了我之前的回答。謝謝你的提示 – user1512999 2012-07-16 09:37:26

+0

它仍然沒有回答問題 - 他想用**標準**或**限制**解決這個問題,而不是HQL。話雖如此,但他爲什麼說這個限制並不明顯,因爲他不打算以妨礙HQL查詢的方式來使用這些標準。您的解決方案比他的解決方案更簡潔,更高效,更易於閱讀和維護。 – Kkkev 2012-07-16 18:22:07

0

沒有任何可這樣做限制。您必須創建自己的Criterion子類,它可以生成適當的SQL,或使用Restrictions.sqlRestriction()

在SQL,在Oracle中,SQL限制可能看起來像以下:

to_date(c.year || '-' || c.month || '-01', 'YYYY-MM-DD') between :startDate and :endDate) 
-1

感謝您的答案@JB Nizet告訴正確的做法,但它是從本地的SQL。我已經嘗試以下成功....

public List<CommissionSummary> getCommissionSummary(AdvisorReportForm advisorReportForm) { 
     Criteria criteria = getSession().createCriteria(CommissionSummary.class); 
     if (advisorReportForm.getAdvisorId() != null && advisorReportForm.getAdvisorId() > 0) { 
      criteria.add(Restrictions.eq("advisorCode", advisorReportForm.getAdvisorId().toString())); 
     } 

     if (advisorReportForm.getFromDate() != null && advisorReportForm.getToDate() != null) { 
      Calendar calFrom = Calendar.getInstance(); 
      calFrom.setTime(advisorReportForm.getFromDate()); 

      Calendar calTo = Calendar.getInstance(); 
      calTo.setTime(advisorReportForm.getToDate()); 

      Criterion crit1 = Restrictions.eq("month", calFrom.get(Calendar.MONTH) + 1); 
      Criterion crit2 = Restrictions.eq("year", calFrom.get(Calendar.YEAR)); 
      Criterion critMonthYear1 = Restrictions.and(crit1, crit2); 
      calFrom.add(Calendar.MONTH, 1); // increment loop by month 

      Criterion critAll = critMonthYear1; 
      while (calFrom.getTimeInMillis() < calTo.getTimeInMillis()) { 
       Criterion crit1Loop = Restrictions.eq("month", calFrom.get(Calendar.MONTH) + 1); 
       Criterion crit2Loop = Restrictions.eq("year", calFrom.get(Calendar.YEAR)); 
       Criterion critMonthYearLoop = Restrictions.and(crit1Loop, crit2Loop); 
       critAll = Restrictions.or(critAll, critMonthYearLoop); 
       calFrom.add(Calendar.MONTH, 1); // increment loop by month 
      } 
      criteria.add(critAll); 

     } 

     return criteria.list(); 
    } 

從日期到目前的差異是驗證最多可達6個月。我沒有看到太多的性能問題。所以用這個。

供您參考這裏生成的SQL

SELECT * FROM CommissionSummary this_ 
WHERE this_.advisorCode=1 
AND (((((this_.month=11 AND this_.year=2011) OR (this_.month=12 AND this_.year=2011)) OR (this_.month=1 AND this_.year=2012)) 
OR (this_.month=2 AND this_.year=2012)) OR (this_.month=3 AND this_.year=2012))