The article shows how to pass a query hint using the hintplan extension when the query is getting generated by hibernate. The query hints are passed to the optimiser for choosing a more optimised plan for the query.
Hibernate doesn’t provide a direct method to resolve the issue. As a solution, we can use the Hibernate StatementInspector
to intercept and modify auto-generated SQL statements i.e.
public class HintStatementInspector implements StatementInspector {
@Override
public String inspect(String sql) {
// check if pg_plan_hint hint is available
if (sql.startsWith("/* /\\*+")) {
// fix first part of the hint comment
sql = sql.replaceFirst(Pattern.quote("/* /\\*+"), Matcher.quoteReplacement("/*+"));
// fix last part of the hint comment
sql = sql.replaceFirst(Pattern.quote("*\\/ */"), Matcher.quoteReplacement("*/"));
}
return sql;
}
}
hibernate.cfg.xml
<property name="hibernate.use_sql_comments">true</property>
<property name="hibernate.session_factory.statement_inspector">com.pgedge.example.HintStatementInspector</property>
Try an example query
String hql = "select id, name from City where id = 170505378935607296";
// add pg_plan_hint hint, you may adopt different marks as well and process them in `HintStatementInspector` as per convenience
Query query = session.createQuery(hql).setComment("/*+ SeqScan(c1_0) */");
List results = query.getResultList();
You can see that hint is being passed to PostgreSQL query optimiser i.e.
PostgreSQL log
2024-06-27 10:44:56.722 PKT [PostgreSQL JDBC Driver, asif, postgres , 3397633] LOG: execute <unnamed>: /*+ SeqScan(c1_0) */ select c1_0.id,c1_0.name from public.City c1_0 where c1_0.id=170505378935607296