【问题标题】:How to add SQL-Server query hint in Hibernate Criteria API如何在 Hibernate Criteria API 中添加 SQL-Server 查询提示
【发布时间】:2018-10-15 06:57:22
【问题描述】:

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

最近我发现了一个遭受参数嗅探的查询,因此我想添加一个OPTION (RECOMPILE) 作为查询提示。不过虽然Hibernate似乎支持query hints for Criteria API添加了

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

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

有什么想法吗?

【问题讨论】:

    标签: java sql-server hibernate criteria-api


    【解决方案1】:

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

    我找到的最佳解决方案是自己实现对 SQL-Server 的支持(您也可以执行类似 criteria.add(Restrictions.sqlRestriction("1=1 OPTION (RECOMPILE) ")); 的操作,但这几乎是一种 hack,如果您想向询问) 。

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

    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
    

    【讨论】:

      【解决方案2】:

      在 org.hibernate.dialect.SQLServer2012Dialect 类中添加了提示,因此请确保属性具有 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 添加到参数中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多