java - 如何将 "Optimizer hint"插入到 Hibernate 条件 api 查询

标签 java sql oracle hibernate criteria

我有一个使用条件 api 动态组合在一起的 hibernate 查询。 如果按原样执行,它会生成非常慢的查询。

但我注意到,如果我在查询前加上/*+ FIRST_ROWS(10) */,它们的速度会提高大约 1000%。我如何使用标准 api 执行此操作?

我尝试了 criteria.setComment(..),但这似乎被忽略了。

在 hibernate 文档中,3.4.1.7。提到了查询提示,但它明确指出:“请注意,这些不是 SQL 查询提示”

查询的结果将被分页,所以在 99% 的情况下我会显示结果 1-10。

最佳答案

我有另一个通用解决方案,应该适用于每个条件查询:
使用标准注释和 Hibernate 拦截器将最终 SQL 更改为数据库。
(我在 Hibernate 3.3 中使用它,但应该适用于每个版本,拦截器的注册可能不同。)

在您的查询代码中使用:

criteria.setComment("$HINT$ push_pred(viewAlias)");

写一个拦截器来改变SQL文本(这个使用commons.lang3.StringUtils):

public class HibernateEntityInterceptor extends EmptyInterceptor {

@Override
public String onPrepareStatement(String sql) {
    if (sql.startsWith("/* $HINT$")) {
        String hintText = StringUtils.substringBetween(sql, "/* $HINT$", "*/");
        sql = sql.replaceFirst("select ", "select /*+" + hintText + "*/ ");
    }
    return sql;
}

以上是针对 Oracle 的,但应该可以针对每个 DBMS 轻松调整。
也许你可以/应该为提示标记“$HINT$”创建一个常量。
日志记录也应该完成(这样你就可以很容易地看到拦截器的正确调用),为了简单起见,我在上面省略了它。

拦截器必须注册。在 Spring 中,这是在 applicationContext.xml 中完成的:

<bean id="entityListener" class="your.package.HibernateEntityInterceptor"/>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="entityInterceptor" ref="entityListener"/>
    [...]

或者(从 Hibernate 3.3 文档复制):

A Session-scoped interceptor is specified when a session is opened using one of the overloaded SessionFactory.openSession() methods accepting an Interceptor.

Session session = sf.openSession( new HibernateEntityInterceptor() );

A SessionFactory-scoped interceptor is registered with the Configuration object prior to building the SessionFactory. Unless a session is opened explicitly specifying the interceptor to use, the supplied interceptor will be applied to all sessions opened from that SessionFactory. SessionFactory-scoped interceptors must be thread safe. Ensure that you do not store session-specific states, since multiple sessions will use this interceptor potentially concurrently.

new Configuration().setInterceptor( new HibernateEntityInterceptor() );

关于java - 如何将 "Optimizer hint"插入到 Hibernate 条件 api 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1327503/

相关文章:

php - 使用 Neo4j 的新闻源中帖子/更新的时间衰减因子

c# - Oracle中如何获取存储过程参数类型和大小?

mysql - 查询将每一行的字段与同一表的所有其他行的字段进行比较?

java - Tomcat JDBC Conencton Pool + MySQL 给出 "Broken pipe"问题,即使有连接验证

java - 压入和弹出整数到堆栈,什么结果是不可能的

java - 将文件读取为二维字符数组

sql - 如何按小时从oracle数据库中获取数据

Java将字符串转换为日期然后比较

sql - 复合键每组行的序列号

SQLite JOIN WHERE 不在多个表中