0

我正在尝试在休眠中注册一个函数以在 mysql 5 中执行按位与 (&) 和按位或 (|)。

到目前为止,我有一个自定义的 mysql 方言:

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">com.***.hibernate.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
    <property name="packagesToScan">...</property>
</bean>

这是我的自定义方言代码:

public class MySQLDialect extends org.hibernate.dialect.MySQL5Dialect {
    public MySQLDialect() {
        super();
        registerFunction("bitwise_and", new BitwiseAndFunction("bitwise_and"));
    }
}

这是我的自定义函数:

public class BitwiseAndFunction extends StandardSQLFunction implements SQLFunction {

public BitwiseAndFunction(String name) {
    super(name);
}

public BitwiseAndFunction(String name, Type type) {
    super(name, type);
}

public String render(List args, SessionFactoryImplementor factory)
        throws QueryException {
    if (args.size() != 2) {
        throw new IllegalArgumentException(
                "the function must be passed 2 arguments");
    }
    StringBuffer buffer = new StringBuffer(args.get(0).toString());
    buffer.append(" & ").append(args.get(1));
    return buffer.toString();
}

}

问题是每当我在 HQL 查询中使用 bitwise_and 时,它都会给我一个很长的堆栈跟踪,开头是:

org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: bitwise_and near line 1, column 354 [select sqrt(pow(rideRequest.startLatitude - p.latitude, 2) + pow(rideRequest.startLongitude - p.longitude, 2)) as distance, p.polyLine.rideOffer as rideOffer, p.polyLine.rideOffer.user, p.polyLine.rideOffer.user.role from com.freeride.lib.domain.Point p, com.freeride.lib.domain.RideRequest rideRequest where rideRequest.id=? and (rideOffer.permissions bitwise_and rideRequest.permissions) = rideRequest.permissions group by p.polyLine.rideOffer order by distance asc]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:79)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:276)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:180)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:105)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
4

1 回答 1

4

我找到了自己的解决方案。执行自定义 hql 函数的旧方法在 Hibernate 3.6.0 中已弃用,因此在我更新的版本(4.2.5)中,我不得不使用:

import java.lang.Integer;
public class MyDialect extends org.hibernate.dialect.MySQL5Dialect {
    public MyDialect() {
        super();
        //THIS DOES NOT WORK!
        registerFunction("bitwise_andOne", new BitwiseAndFunction("poop"));
        //THIS WORKS!
        registerFunction("bitwise_andTwo", new SQLFunctionTemplate(IntegerType.INSTANCE, "(?1 & ?2)"));
    }
}

基本上,第二种方法有效,而前一种方法无效。我不知道为什么。

您可以在任何 hql 查询中以编程方式调用 bitwise_and2。例如:

sessionFactory.getCurrentSession.createQuery("select * from people person where bitwise_andTwo(person.permissions, 7)

生成的 sql 将类似于

select * from people where people.permissions & 7 = 权限

这解决了我的问题。

于 2013-09-17T18:16:41.567 回答