I have another general solution that should work for every Criteria request:
use the standard comment and Hibernate interceptor, modifying the resulting SQL into the database.
(I used it with Hibernate 3.3, but should be used for each version, registration of the Interceptor may be different.)
In your request code use:
criteria.setComment("$HINT$ push_pred(viewAlias)");
Record an interceptor to modify SQL text (this one uses 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; }
Above for Oracle, but it needs to be easily configured for each DBMS. Perhaps you can / should create a constant for the hint marker "$ HINT $".
Logging should be done too (so you can easily see the correct interceptor call), I left it higher for simplicity.
The interceptor must be registered. In Spring, this is done in applicationContext.xml :
<bean id="entityListener" class="your.package.HibernateEntityInterceptor"/> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="entityInterceptor" ref="entityListener"/> [...]
Or (copy from Hibernate 3.3 docs):
A session-bound interceptor is specified when a session is opened using one of the overloaded methods of SessionFactory.openSession () receiving an interceptor.
Session session = sf.openSession( new HibernateEntityInterceptor() );
The SessionFactory interceptor is registered using the Configuration Object prior to creating the SessionFactory. If the session is explicitly opened, indicating the use of an interceptor, the delivered interceptor will be applied to all sessions opened from this SessionFactory. SessionFactory interceptors should be threads safe. Make sure that you do not save session-specific states, as multiple sessions will use this interceptor potentially simultaneously.
new Configuration().setInterceptor( new HibernateEntityInterceptor() );