MySQL相關——MySQL針對varchar排序問題

最近做項目,在設計數據庫表的時候一時疏忽把用於排序的字段設爲了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了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章