问题
Let's say I have a due date and a reminder timespan. How do I find the ones where due date is less than current date + reminder with Hibernate 3.6 criteria queries? In other words, I want to find my Events I've displayed the reminder. The reminder is a Long marking when the reminder should be sent either days or milliseconds, whichever is easier.
To summarize, my entities are following:
java.util.Date Event.DueDate
Long Event.Type.Reminder.Before // (in days or millis)
Examples
Today is 2012-06-11.
Included:
DueDate is 2012-06-15 and Before is 30 days.
Excluded:
DueDate is 2012-06-15 and Before is 1 day.
回答1:
Ultimately this is just what ANSI SQL calls date/time arithmetic and specifically you are looking for INTERVAL datatype handling. Unfortunately, databases vary widely on support for INTERVAL datatype. I really want to support this in HQL (and possibly criterias, although that relies on agreement in the JPA spec committee). The difficulty, like I said, is the varied (if any) support for intervals.
The best bet at the moment (through Hibernate 4.1) is to provide a custom function (org.hibernate.dialect.function.SQLFunction
) registered with either the Dialect
(search google to see how this is done) or the "custom function registry" (org.hibernate.cfg.Configuration#addSqlFunction
). You'd probably want this to render to your database-specific representation of date-arith with an interval.
Here is an example using the Oracle NUMTODSINTERVAL
function:
public class MySqlFunction implements SQLFunction
{
public Type getReturnType(Type firstArgumentType,
Mapping mapping) throws QueryException
{
return TimestampType.INSTANCE;
}
public String render(Type firstArgumentType,
List arguments,
SessionFactoryImplementor factory) throws QueryException
{
// Arguments are already interpreted into sql variants...
final String dueDateArg = arguments.get( 0 );
final String beforeArg = arguments.get( 1 );
// Again, using the Oracle-specific NUMTODSINTERVAL
// function and using days as the unit...
return dueDateArg + " + numtodsinterval(" + beforeArg + ", 'day')";
}
public boolean hasArguments() { return true; }
public boolean hasParenthesesIfNoArguments() { return false; }
}
You would use this in HQL like:
select ...
from Event e
where current_date() between e.dueDate and
interval_date_calc( e.dueDate, e.before )
where 'interval_date_calc' is the name under which you registered your SQLFunction.
来源:https://stackoverflow.com/questions/10981736/hibernate-and-date-comparisons