When I attempt to save an object containing a <set> of <composite-element>s, I get the following ClassCastException:
Quote:
java.lang.Long cannot be cast to java.lang.Integer
java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer
at org.hibernate.type.descriptor.java.IntegerTypeDescriptor.unwrap(IntegerTypeDescriptor.java:36)
at org.hibernate.type.descriptor.sql.IntegerTypeDescriptor$1.doBind(IntegerTypeDescriptor.java:52)
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:91)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:282)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:277)
at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:340)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:815)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1203)
at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:188)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at persistence.GoodManager.saveGood(GoodManager.java:45)
I've hunted high and low through the forums and elsewhere, and there are various reports of similar problems... it sounds like the issue is due to the statement that attempts to insert the composite element record - it tries to bind one of the foreign key identifiers to the statement, and casts it to an Integer when it its a Long. I could not find any solutions to the problem however.
I'm using the "identity" generator strategy, though I've tried the increment also with the same results. I've also tried changing the type of my identifiers from Long to Integer and still get the same error.
In desperation, I'm next going to try a different database, and possibly try using strings for my ids.
I'm using Derby for my database, mapping files follow.
The object that contains the collection is the Blueprint, the collection is of BPIngredients, which consist of a number of Goods (to represent a many-to-many link between Blueprints and their ingredients.
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="eveObjects.Blueprint" table="BLUEPRINT">
<id name="id" type="long" column="ID">
<generator class="identity"/>
</id>
<property name="name" type="string" column="NAME" unique="true" not-null="true"/>
<property name="materialEfficiency" type="integer" column="MATERIAL_EFFICIENCY"/>
<property name="productionEfficiency" type="integer" column="PRODUCTION_EFFICIENCY"/>
<property name="buildTime" type="integer" column="BUILD_TIME"/>
<property name="productQuantity" type="integer" column="PRODUCT_QUANTITY"/>
<one-to-one name="product" class="eveObjects.BuildableGood" property-ref="sourceBlueprint"/>
<property name="baseCopyTime" type="integer" column="BASE_COPY_TIME"/>
<property name="maxCopyRuns" type="integer" column="MAX_COPY_RUNS"/>
<set name="optimalIngredientList" table="BLUEPRINT_INGREDIENT">
<key column="BLUEPRINT_ID"/>
<composite-element class="itemManipulation.BPIngredient">
<many-to-one name="good" column="GOOD_ID" not-null="true" class="eveObjects.Good"/>
<property name="quantity" type="integer" not-null="true" column="QUANTITY"/>
<property name="meApplies" type="boolean" not-null="true" column="ME_APPLIES"/>
</composite-element>
</set>
<joined-subclass name="eveObjects.T1Blueprint" table="T1_BLUEPRINT">
<key column="T1_BLUEPRINT_ID"/>
</joined-subclass>
</class>
</hibernate-mapping>
The Good class
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="eveObjects.Good" table="GOOD">
<id name="id" type="long" column="ID">
<generator class="identity"/>
</id>
<property name="name" type="string" column="NAME" not-null="true" unique="true"/>
<property name="buyCost" type="float" column="BUY_COST"/>
<property name="sellCost" type="float" column="SELL_COST"/>
<joined-subclass name="eveObjects.BuildableGood" table="BUILDABLE_GOOD">
<key column="BUILDABLE_GOOD_ID"/>
<property name="preferToBuild" type="boolean" column="PREFER_TO_BUILD" />
<many-to-one name="sourceBlueprint" class="eveObjects.Blueprint" column="SOURCE_BLUEPRINT" unique="true" cascade="save-update"/>
</joined-subclass>
<joined-subclass name="eveObjects.NonbuildableGood" table="NONBUILDABLE_GOOD">
<key column="NONBUILDABLE_GOOD_ID"/>
<joined-subclass name="eveObjects.Datacore" table="DATACORE">
<key column="DATACORE_ID"/>
</joined-subclass>
<joined-subclass name="eveObjects.Decryptor" table="DECRYPTOR">
<key column="DECRYPTOR_ID"/>
<property name="meAffect" type="integer" column="ME_AFFECT"/>
<property name="peAffect" type="integer" column="PE_AFFECT"/>
<property name="runAffect" type="integer" column="RUN_AFFECT"/>
<property name="chanceAffect" type="float" column="CHANCE_AFFECT"/>
<!-- TODO how to do enum property? -->
</joined-subclass>
</joined-subclass>
</class>
</hibernate-mapping>
The code that blows up:
Code:
blueprint = new T1Blueprint("Test Blueprint", -4, 0, 0, 1, 0, 0);
blueprint.addIngredient(new BPIngredient(nonbuildable, 2, true));
buildable = new BuildableGood("Buildable", 4.5f, 6.6f, true, blueprint);
blueprint.setProduct(buildable);
session.saveOrUpdate(buildable);