最近做項目,在設計數據庫表的時候一時疏忽把用於排序的字段設爲了varchar類型,最後查詢的時候發現了問題,也懶着改數據庫了,就研究如何把varchar類型轉成number再排序
寫SQL語句比較簡單,最省事的處理:
select * from table order by (varcharOrderCol + 0);
比較文藝一點的:
select * from table order by CONVERT(varcharOrderCol, SIGNED);
問題是我項目中用的都是hibernate的Criteria做查詢,這樣並不能直接用,後來又研究了一下
可以重寫一下org.hibernate.criterion.Order,代碼如下:
import java.sql.Types;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.criterion.Order;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.type.Type;
public class VarcharOrder extends Order {
private static final long serialVersionUID = 1L;
private boolean ascending;
private boolean ignoreCase;
private String propertyName;
@Override
public String toString() {
return "CONVERT( " + propertyName + ", SIGNED) " + (ascending ? "asc" : "desc");
}
@Override
public Order ignoreCase() {
ignoreCase = true;
return this;
}
protected VarcharOrder(String propertyName, boolean ascending) {
super(propertyName, ascending);
this.propertyName = propertyName;
this.ascending = ascending;
}
protected VarcharOrder(String propertyName, String dir) {
super(propertyName, dir.equalsIgnoreCase("ASC") ? true : false);
ascending = dir.equalsIgnoreCase("ASC") ? true : false;
this.propertyName = propertyName;
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName);
Type type = criteriaQuery.getTypeUsingProjection(criteria, propertyName);
StringBuffer fragment = new StringBuffer();
for (int i = 0; i < columns.length; i++) {
SessionFactoryImplementor factory = criteriaQuery.getFactory();
boolean lower = ignoreCase && type.sqlTypes(factory)[i] == Types.VARCHAR;
if (lower) {
fragment.append(factory.getDialect().getLowercaseFunction()).append('(');
}
fragment.append("CONVERT( " + columns[i] + ", SIGNED)");
if (lower)
fragment.append(')');
fragment.append(ascending ? " asc" : " desc");
if (i < columns.length - 1)
fragment.append(", ");
}
return fragment.toString();
}
public static Order asc(String propertyName) {
return new VarcharOrder(propertyName, true);
}
public static Order desc(String propertyName) {
return new VarcharOrder(propertyName, false);
}
}
使用的時候:
criteria.addOrder(VarcharOrder.asc(field));
這樣就OK了!