0. 需求背景
由于需要做位运算,但是JPQL不支持,所以尝试添加自定义函数解决问题
1. 实现步骤
1. SQLFunction接口
package plugin.hql;
import org.hibernate.QueryException;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.Type;
import java.util.List;
public class BitAndFunction implements SQLFunction {
/**
* 是否需要参数
*
* @return 需要参数
*/
@Override
public boolean hasArguments() {
return true;
}
/**
* 如该参数为空,是否需要添加括号
*
* @return 需要
*/
@Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
/**
* 函数返回值类型
*
* @param firstArgumentType
* @param mapping
* @return int类型
*/
@Override
public Type getReturnType(Type firstArgumentType, Mapping mapping) {
return org.hibernate.type.IntegerType.INSTANCE;
}
/**
* 转换方法
*
* @param firstArgumentType 参数类型
* @param arguments 参数
* @param factory session工厂类
* @return 转换后的语句
*/
@Override
public String render(Type firstArgumentType, List arguments,
SessionFactoryImplementor factory) {
// 如该参数长度不为2,那么抛出参数错误
if (arguments.size() != 2) {
throw new IllegalArgumentException("BitAndFunction requires 2 arguments!");
}
// 拼接语句
return arguments.get(0).toString() + " & " + arguments.get(1).toString();
}
}
2. 重写SQL方言类,以MySQL为例
package plugin.hql;
import play.db.jpa.MySQLDialect;
/**
*
*/
public class CustomSQLDialect extends MySQLDialect {
}
3. 修改自定义方言类内容
package plugin.hql;
import play.db.jpa.MySQLDialect;
/**
*
*/
public class CustomSQLDialect extends MySQLDialect {
// 重写构造方法,父类的无参构造方法调用后加入自定义函数
public CustomSQLDialect() {
super();
this.registerFunction("bitand", new BitAndFunction());
}
// 顺手把数据库编码改为utf8mb4
@Override
public String getTableTypeString() {
return " ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
}
}
4. 在项目中使用自定义函数
Query query = entityManager.createQuery("SELECT m FROM Menu m WHERE bitand(m.permissions,4) = 4");