So I ran the API through the debugger and had quite a few methods on how I thought I could solve the ability to translate HQL to SQL, but classes like the SessionImpl and SessionFactoryImpl are all final, so I could not successfully implement a Decorator Pattern or any clear extension of their functionality. Essentially the find method did most of what I need to do. It submitted all queries into the QueryTranslator and returned an array of QueryTranslators, which contains the SQL String. This is all I needed, but of course the code continues to process those QueryTranslators against the database in the list command. So unfortunately, my only solution was to utilize QueryTranslator as a utility class. This is the following code that I am testing/implementing:
Code:
public static String translateHQLtoSQL( Session hibernateSession,
String hqlString, boolean scalar ) throws HibernateException
{
//We jave a helper class to load the Hibernate Configurations
Properties props =
HibernateHelper.getHibernateConfigurationProperties( );
String sqlQuery = "";
try
{
//Take the loaded Hibernate Configuration and create a Settings class
Settings hibernateSettings = SettingsFactory.buildSettings( props );
//The SessionImpl stores a SessionFactoryImpl but returns it as a SessionFactoryImplementor
//SessionFactoryImpl implements SessionFactoryImplementor
SessionFactoryImpl sessionFactory =
( SessionFactoryImpl )hibernateSession.getSessionFactory( );
//Then pass the HQL query into the creation of a QueryTranslator
QueryTranslator queryTranslator = new QueryTranslator( hqlString );
//Compile the HQL with the sessionFactory and hibernateSettings
queryTranslator.compile( sessionFactory,
hibernateSettings.getQuerySubstitutions( ), scalar );
//Retrieve the SQL statement from the SQL String
sqlQuery = queryTranslator.getSQLString( );
}
catch ( HibernateException he )
{
ArchTracer.exitScope( he );
HibernateHelper.handleHibernateException( he );
}
return sqlQuery;
}
public int getGovernedSearchConstantResult( String sqlQuery, List paramaters )
throws MaximumResultsExceededException, DatabaseException
{
int rowCount = 0;
String selectConstant = "";
PreparedStatement statement = null;
Connection connection = null;
ResultSet resultSet = null;
try
{
//Use a utility class to remove the select statement from the SQL
//May seem odd but the utility class was created for parsing HQL,
//But works the same for HQL and SQL
String excludeSelect =
HQLStringParser.getHQLFragmentAfter( sqlQuery, FROM_CLAUSE );
//Add the "select 1" string to the beginning and the "read only"
//for performance
selectConstant =
SELECT_CONSTANT_CLAUSE + excludeSelect + READ_ONLY_CLAUSE;
connection = getConnection( );
statement = connection.prepareStatement( selectConstant );
//Use a private method that loops through a list of parameters and
//sets them as Objects to the PreparedStatement
//This is the next hook that I have to create into Hibernate
//because their no functionality to pass in a HQL type
//and retrieve the matching Java Type. I need this
//to correctly create the PreparedStatement
this.setQueryParameters( statement, paramaters );
//Execute the SQL
resultSet = statement.executeQuery( );
//For speed, looping through the resultset is faster than using
while ( ( rowCount <= ABSOLUTE_MAX_RESULTS ) && resultSet.next( ) )
{
rowCount++;
}
if ( rowCount > ABSOLUTE_MAX_RESULTS )
{
ArchTracer.high( "Search query returned more than " +
ABSOLUTE_MAX_RESULTS + " results." );
throw new MaximumResultsExceededException( "Returned too many rows: ",
"error.technical.persistence.MaximumResultsExceeded",
new Object[] { String.valueOf( ABSOLUTE_MAX_RESULTS ) } );
}
}
catch ( SQLException sqle )
{
throw new DatabaseException( "The governed search query for max results limit failed",
sqle, "error.database.QueryFailed" );
}
finally
{
JdbcHelper.closeAll( connection, statement, resultSet );
}
return rowCount;
}
Thanks for the help...It would be nice if in Hibernate 3, there was extensibility to SessionImpl or SessionFactoryImpl that way I could have allowed the Hibernate architecture to work properly, just decorate or over the Find method in the SessionImpl to only return the list of QueryTranslators and not actually hit the database.
-jay