如何在 Hibernate Criteria API 中添加 SQL-Server 查询提示

How to add SQL-Server query hint in Hibernate Criteria API

我们正在使用 MS SQL-Server 和 Hibernate Criteria API。

最近我发现一个查询存在参数嗅探问题,所以我想添加一个 OPTION (RECOMPILE) 作为查询提示。但是尽管 Hibernate 似乎支持 query hints for Criteria API 添加的

criteria.addQueryHint("OPTION (RECOMPILE)");

似乎没有任何效果(记录的 SQL 不包含任何提示)。

有什么想法吗?

Hibernate Criteria API 似乎只支持 Oracle 数据库的查询提示。

我找到的最好的解决方案是自己实现对 SQL-Server 的支持(你也可以做类似 criteria.add(Restrictions.sqlRestriction("1=1 OPTION (RECOMPILE) ")); 的事情,但这几乎是一个技巧,如果你例如,想要向查询添加排序)。

我使用 Oracle 的 Hibernate 实现作为蓝图(查看 Oracle8iDialect)。对于我的用例,实现一个将查询提示附加到查询末尾的版本就足够了(因为 OPTION 子句总是在查询末尾)。

package de.mystuff.hibernate;

import java.util.List;

import org.hibernate.annotations.common.util.StringHelper;
import org.hibernate.dialect.SQLServer2008Dialect;


/**
 * Special version of {@link SQLServer2008Dialect} which adds a simple query hint support.
 */
public class MySQLServer2012Dialect extends org.hibernate.dialect.SQLServer2012Dialect {


    /**
     * {@inheritDoc}
     * <p>
     * Currently this is a pretty simple query hint implementation. It just concatenates all SQL hints and adds them to the end of the query. This is fine for
     * e.g. {@code OPTION (RECOMPILE)}.
     */
    @Override
    public String getQueryHintString(String sql, List<String> hints) {
        if (hints.isEmpty()) {
            // no query hints at all
            return sql;
        }

        // concatenate all hints
        final String hint = StringHelper.join(", ", hints.iterator());

        if (StringHelper.isEmpty(hint)) {
            // all query hints are empty
            return sql;
        }

        return sql + " " + hint;
    }

}

提醒您必须告诉 Hibernate 使用支持方言的查询提示:

hibernate.dialect=de.mystuff.hibernate.MySQLServer2012Dialect

已将提示添加到 org.hibernate.dialect.SQLServer2012Dialect class,因此请确保属性具有 hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect

使用 javax.persistence.EntityManager:

var query = entityManager.createQuery(criteriaQuery).unwrap(org.hibernate.query.Query.class);
query.addQueryHint("RECOMPILE");
return query.list();

方言会自动在参数前添加 OPTION