When upgrading from 3.0.1 to 3.0.5, we discovered that a SessionFactory can no longer be created from our mapping.
It appears that if a subclass is abstract and has no children, the SessionFactory creation throws a NoSuchElementException. (See stack trace below.)
In the mapping below, Rule and InclusionRule (its child) are both abstract. InclusionRule has no children at this stage of development.
When looking at the Hibernate source, we noticed it expects all mapped abstract classes to have at least one non-abstract child, but the exception is vague and gives little indication of the true error.
We were able to get around the exception by mapping a single (non-abstract) placeholder class as a child of the abstract one. (Seen below as NullInclusionRule.)
No bug posted. (Not sure this is one.)
Hibernate version: 3.0.5
Mapping documents:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- Abstract class -->
<class name="com.cpex.mpv.rules.Rule" table="RULE">
<id name="id" column="id" type="int" unsaved-value="0">
<generator class="native" />
</id>
<discriminator column="TYPE" />
<property name="defaults"
type="com.cpex.mpv.persistence.PropertiesUserType"
column="defaults" />
<!-- Abstract class -->
<subclass name="com.cpex.mpv.rules.InclusionRule"
discriminator-value="INCLUSION">
<!-- Mapping non-abstract placeholder to avoid NoSuchElementException -->
<subclass name="com.cpex.mpv.rules.NullInclusionRule"
discriminator-value="NULL_INCLUSION" />
</subclass>
<!-- Abstract class -->
<subclass name="com.cpex.mpv.rules.ValidationRule"
discriminator-value="VALIDATION">
<!-- Non-abstract sub-classes -->
<subclass name="com.cpex.mpv.rules.IndexValidationRule"
discriminator-value="INDEX_VALIDATION" />
<subclass name="com.cpex.mpv.rules.OptionGapValidationRule"
discriminator-value="GAP_VALIDATION" />
<subclass name="com.cpex.mpv.rules.ComputePackagingRule"
discriminator-value="COMPUTE_PACKAGING_VALIDATION" />
<subclass
name="com.cpex.mpv.rules.ComputeImpliedVolatilityRule"
discriminator-value="COMPUTE_IV_VALIDATION" />
<subclass name="com.cpex.mpv.rules.OptionAtmValidationRule"
discriminator-value="ATM_VALIDATION" />
<subclass name="com.cpex.mpv.rules.FinishValidationRule"
discriminator-value="FINISH_VALIDATION" />
<subclass name="com.cpex.mpv.rules.RangeValidationRule"
discriminator-value="RANGE_VALIDATION">
<subclass name="com.cpex.mpv.rules.IvValidationRule"
discriminator-value="IV_VALIDATION" />
</subclass>
<subclass
name="com.cpex.mpv.rules.OptionUnderlyingValidationRule"
discriminator-value="UNDERLYING_VALIDATION" />
</subclass>
</class>
</hibernate-mapping>
Full stack trace of any exception that occurs:Code:
15:47:45,574 ERROR HibernateUtil - Initial SessionFactory creation failed.
java.util.NoSuchElementException
at java.util.AbstractList$Itr.next(AbstractList.java:427)
at org.hibernate.sql.InFragment.toFragmentString(InFragment.java:80)
at org.hibernate.persister.entity.SingleTableEntityPersister.discriminatorFilterFragment(SingleTableEntityPersister.java:495)
at org.hibernate.persister.entity.SingleTableEntityPersister.filterFragment(SingleTableEntityPersister.java:467)
at org.hibernate.persister.entity.BasicEntityPersister.filterFragment(BasicEntityPersister.java:2240)
at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:85)
at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:59)
at org.hibernate.loader.entity.BatchingEntityLoader.createBatchingEntityLoader(BatchingEntityLoader.java:98)
at org.hibernate.persister.entity.BasicEntityPersister.createEntityLoader(BasicEntityPersister.java:1431)
at org.hibernate.persister.entity.BasicEntityPersister.createEntityLoader(BasicEntityPersister.java:1435)
at org.hibernate.persister.entity.BasicEntityPersister.createLoaders(BasicEntityPersister.java:2439)
at org.hibernate.persister.entity.BasicEntityPersister.postInstantiate(BasicEntityPersister.java:2432)
at org.hibernate.persister.entity.SingleTableEntityPersister.postInstantiate(SingleTableEntityPersister.java:656)
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:244)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1005)
at com.cpex.mpv.persistence.HibernateUtil.<clinit>(HibernateUtil.java:58)
...
Name and version of the database you are using: Oracle 9i
The generated SQL (show_sql=true): N/A
Debug level Hibernate log excerpt: N/A