Hi Everybody,
I don't know if it is really is a BUG, but I would like the folks at hibernate to definatly have a look at this problem.
After roughly a week and half of painful debugging, I figured out the problem with hibernate generating only a "PARTIAL QUERY" for the below mentioned code. (Right at the end of this post)
The query generated was: "SELECT FROM"
The query I was expecting:
select catpersist0_.CAT_ID as CAT_ID, catpersist0_.NAME as NAME0_, catpersist0_.sex as sex0_, catpersist0_.weight as weight0_ from Cat catpersist0_
The problem was that hibernate was not able to pick up the Persister class for the dynamic class mention in the mapping xml.
Though the HashMap of Persisters class Mapping are well populated in the SessionFactoryImpl class constructor, there seems to be a problem while looking up or while retrieving persister class object from the same Map object.
The look up process in my scenario starts from the getEntityPersisterUsingImports (String className)' method of the QueryTranslatorImpl class.
While building the Persisters class mapping inside the SessionFactoryImpl class , entity name used for the dynamic class in the mapping XML is used as the key and an instance of the persister class is used as the value for the Map entry.
While looking up the Persister class object for a given entity name from the FromParser.java 's token() method, FromParser uses getEntityPersisterUsingImports(token) method of the QueryTranslatorImpl.java class.
The getEntityPersisterUsingImports method in the QueryTranslatorImpl.java class, in turn retrieves the the actual java Map implementation class name for the given entity-name from the mapping XML and uses the java Map class name as a parameter to the method, getEntityPersister(String) method.
Which causes the SessionFactoryImpl class to return 'null' instead of a valid Persister class object. Since the 'classPersistersByName' Map object contain entity-name as the key, while the incoming parameter is a Map implementation class name to which entity-name maps to.
This leads to incomplete generation of SQL in hibernate.
I am not sure if this is a bug, or there is something wrong in my implementation which causes the Hibernate to run into these parts of the code which may have been meant for some other purpose.
Following is the patch that i applied in the org.hibernate.hql.QueryTranslatorImpl.java
******************************************************
Queryable getEntityPersisterUsingImports(String className) {
final String importedClassName = factory.getImportedClassName(className);
if (importedClassName==null) return null;
try {
//return ( Queryable ) factory.getEntityPersister(importedClassName); //### This is the buggy line ###
return ( Queryable ) factory.getEntityPersister(className);
}
catch (MappingException me) {
return null;
}
}
*************************************************************
After the fix i ran few examples and some of my own programs which were previoulsy running/not-running both seem to work fine.
I am surely interested to know about it. Please respond to the post or email to me at
madhusudanmk@yahoo.com.
Cheers,
Madhusudan M Krishnamurthy
Hibernate version:3.0
Mapping documents:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping auto-import="false">
<import class="java.util.Map" rename="CatPersistentMap"/>
<dynamic-class entity-name="CatPersistentMap" table="Cat" discriminator-value="C" persister="org.hibernate.persister.SingleTableEntityPersister">
<id name="id" type="string" unsaved-value="null" >
<column name="CAT_ID" sql-type="char(32)" not-null="true"/>
<generator class="uuid.hex"/>
</id>
<property name="name" type="java.lang.String">
<column name="NAME" length="16" not-null="true"/>
</property>
<property name="sex" type="char"/>
<property name="weight" type="float" />
</dynamic-class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
transaction = session.beginTransaction();
String hqlQuery = "from CatPersistentMap catPersistentMap";
Query query = session.createQuery(hqlQuery);
System.out.println("SQL :: " + query.getQueryString());
List catList = query.list();
if (catList != null && !catList.isEmpty())
{
Iterator catIterator = catList.iterator();
while (catIterator.hasNext())
{
Map catMap = (Map) catIterator.next();
System.out.println("Cat Map :: " + catMap);
}
}
else
System.out.println("Empty records");
transaction.commit();
Full stack trace of any exception that occurs:
java.sql.SQLException: ORA-00936: missing expression
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:289)
at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:579)
at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1894)
at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteDescribe(TTC7Protocol.java:831)
at oracle.jdbc.driver.OracleStatement.doExecuteQuery(OracleStatement.java:2496)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2840)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:608)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:536)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:96)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1044)
at org.hibernate.loader.Loader.doQuery(Loader.java:321)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:167)
at org.hibernate.loader.Loader.doList(Loader.java:1201)
at org.hibernate.loader.Loader.list(Loader.java:1186)
at org.hibernate.hql.QueryTranslatorImpl.list(QueryTranslatorImpl.java:872)
at org.hibernate.impl.SessionImpl.find(SessionImpl.java:812)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:84)
at com.accelrys.platform.test.TestCatQuery.executeCustomHQL(TestCatQuery.java:164)
at com.accelrys.platform.test.TestCatQuery.main(TestCatQuery.java:53)
SEVERE: Could not execute query
java.sql.SQLException: ORA-00936: missing expression
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:289)
at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:579)
at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1894)
at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteDescribe(TTC7Protocol.java:831)
at oracle.jdbc.driver.OracleStatement.doExecuteQuery(OracleStatement.java:2496)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2840)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:608)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:536)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:96)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1044)
at org.hibernate.loader.Loader.doQuery(Loader.java:321)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:167)
at org.hibernate.loader.Loader.doList(Loader.java:1201)
at org.hibernate.loader.Loader.list(Loader.java:1186)
at org.hibernate.hql.QueryTranslatorImpl.list(QueryTranslatorImpl.java:872)
at org.hibernate.impl.SessionImpl.find(SessionImpl.java:812)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:84)
at com.accelrys.platform.test.TestCatQuery.executeCustomHQL(TestCatQuery.java:164)
at com.accelrys.platform.test.TestCatQuery.main(TestCatQuery.java:53)
Name and version of the database you are using:
Oracle 9i
The generated SQL (show_sql=true):
select from
Debug level Hibernate log excerpt: