按位与运算(&)在许多数据库中都是支持的,遗憾的是,Hibernate 3在HQL中不支持&运算,如果你写了如下的HQL:
where a.id & :mask = :target
则Hibernate报错:exception: unexpected char: '&'.
如何解决此问题?方法是利用Hibernate支持的自定义SQLFunction,定义一个bitand(a,b)的SQLFunction,然后,自己写一个解释器,生成a & b的SQL语句。
要实现一个自定义的SQLFunction,必须实现SQLFunction接口:
/** * for more information, please visit http://www.crackj2ee.com * Copyright_2006, Liao Xuefeng * Created on 2006-4-19 */package com.crackj2ee.dev.hibernate;
import java.util.List;
import org.hibernate.Hibernate;import org.hibernate.QueryException;import org.hibernate.dialect.function.SQLFunction;import org.hibernate.engine.Mapping;import org.hibernate.engine.SessionFactoryImplementor;import org.hibernate.type.Type;
/** * If don't have this 'bitand' function, hibernate will report * exception: unexpected char: '&'. * * @author Xuefeng */public class BitAndFunction implements SQLFunction {
public Type getReturnType(Type type, Mapping mapping) { return Hibernate.LONG; }
public boolean hasArguments() { return true; }
public boolean hasParenthesesIfNoArguments() { return true; }
public String render(List args, SessionFactoryImplementor factory) throws QueryException { if (args.size() != 2) { throw new IllegalArgumentException("BitAndFunction requires 2 arguments!"); } return args.get(0).toString() + " & " + args.get(1).toString(); }
}
然后,根据你使用的数据库方言,派生一个自定义的CustomSQLDialect:
/** * for more information, please visit http://www.crackj2ee.com * Copyright_2006, Liao Xuefeng * Created on 2006-4-19 */package com.crackj2ee.dev.hibernate;
import org.apache.commons.logging.LogFactory;import org.hibernate.dialect.SQLServerDialect;
public class CustomSQLDialect extends SQLServerDialect {
public CustomSQLDialect() { super(); registerFunction("bitand", new BitAndFunction()); }
}
我们设定函数名为bitand,参数和返回值均为Hibernate.LONG,现在,用CustomSQLDialect替换配置文件中的设置,然后修改HQL:
where bitand(a.id, :mask) = :target
编译,运行,观察Hibernate的SQL输出,执行成功! |