Reputation: 403
I came across recently was trying to order a Hibernate Criteria Query by two columns of equal importance. Basically what I mean is, if I have a table where one column is a date (createdOnDate) and the other is a date (modifiedOnDate), I’d like to compare all dates in the orderBy clause from Organization object.
for this i tried like this:
session.createCriteria(Organization.class).addOrder(Order.desc("modified_date")).addOrder( Order.desc("created_date") ).list();
But it is sorting all the organizations first based on the modified_date and then again it is sorting using created_date. This means a modified record could appear before any createdOn records, even if the createdOnDate is earlier.
I need sorting happens simaltaneously with created_date & modified_date.
Please help for this.
Thanks in advance.
Upvotes: 4
Views: 6422
Reputation: 931
You can use "COALESCE()" function in sql to take value from two column when first one will be null than it will take second column,
ORDER BY COALESCE( alias_1.modified_date, alias_1.created_date ) ASC;
So it means if value present in "modified_date" column take for sorting if not present than take from "created_date" for sorting.
In hibernate criteria for COALESCE() function i think there is no Order Bean so you can extend and write your own implementation.
Just like this, if wrong please correct me.
public class CoalesceOrder extends Order {
private String[] properties;
protected CoalesceOrder(boolean ascending, String... properties) {
super(properties.toString(), ascending);
this.properties = properties;
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
StringBuilder fragment = new StringBuilder();
StringBuilder exp = new StringBuilder();
fragment.append("COALESCE(");
SessionFactoryImplementor factory = criteriaQuery.getFactory();
for (int j = 0; j < this.properties.length; j++) {
String propertyName = this.properties[j];
String[] columns = criteriaQuery.getColumnsUsingProjection(
criteria, propertyName);
Type type = criteriaQuery.getTypeUsingProjection(criteria,
propertyName);
StringBuilder fragForField = new StringBuilder();
for (int i = 0; i < columns.length; i++) {
final StringBuilder expression = new StringBuilder();
boolean lower = false;
if (super.isIgnoreCase()) {
int sqlType = type.sqlTypes(factory)[i];
lower = sqlType == Types.VARCHAR || sqlType == Types.CHAR
|| sqlType == Types.LONGVARCHAR;
}
if (lower) {
expression.append(
factory.getDialect().getLowercaseFunction())
.append('(');
}
expression.append(columns[i]);
if (lower)
expression.append(')');
fragForField.append(expression.toString());
if (i < columns.length - 1)
fragForField.append(", ");
}
exp.append(fragForField.toString());
if (j < properties.length - 1)
exp.append(", ");
}
exp.append(")");
fragment.append(factory.getDialect().renderOrderByElement(
exp.toString(), null, super.isAscending() ? "asc" : "desc",
factory.getSettings().getDefaultNullPrecedence()));
return fragment.toString();
}
public static Order asc(String... properties) {
return new CoalesceOrder(true, properties);
}
public static Order desc(String... properties) {
return new CoalesceOrder(false, properties);
}
}
you can add Order now like
criteria.addOrder(CoalesceOrder.desc("modified_date", "created_date"));
Upvotes: 5