Reputation: 8971
I have an entity as
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
}
On screen user is entering criteria to fetch the date between 2 dates.
Ex. From 01/Jan/2012 till 30/Jul/2012.
In CommissionSummary entity does not have date column, but it has month and year 2 separate columns.
I want to fetch CommissionSummary records for the period from date and to date given by user, based on month and year column.
So how to achieve this using Hibernate Criteria / Restrictions?
Note: Day field does not have any sense in user inputted from and to date.
Upvotes: 0
Views: 11857
Reputation: 47243
You can break the criterion down into the disjunction of three smaller criteria:
You can write each of those as a conjunction of two simple comparisons. This looks like (not tested!):
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))
);
Upvotes: 3
Reputation: 247
You can use HQL to select what you want:
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();
Upvotes: -1
Reputation: 8971
Thanks for all your answers @JB Nizet has told the correct approach, but which is from native SQL. I have tried below with success....
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();
}
As from date to to date difference is validated max upto 6 months. I don't see much performance issue. So used this.
For your reference here is generated 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))
Upvotes: -1
Reputation: 692121
There's no restriction available to do that. You'll have to create your own Criterion subclass which generates the appropriate SQL, or use Restrictions.sqlRestriction()
.
In SQL, on Oracle, the SQL restriction could look like the following:
to_date(c.year || '-' || c.month || '-01', 'YYYY-MM-DD') between :startDate and :endDate)
Upvotes: 0