Hi,
I've got this claim Object, and it's got a lot of object members. The two of them that are causing me problems are the Upsides and Downsides. As you can see in the mapping file below, each Upside and Downside has a member called Rationale.
For some weird reason, when we save a claim to the database, the number of upsides and downsides for that claim increases. This was really confusing me, so I wrote a really simple servlet to test it. Here's a snippet of the important stuff:
Code:
Code:
CommonQueryFactory mcf = new CommonQueryFactory();
Claim loadedClaim = mcf.findClaim("152967");
Set downsides = loadedClaim.getDownsides();
Iterator dIterator = downsides.iterator();
myWriter.println("downsides:");
while(dIterator.hasNext()) {
Downside currD = (Downside)dIterator.next();
myWriter.println(currD.getDownside() + "");
}
try {
tx = session.beginTransaction();
session.saveOrUpdate(claim);
tx.commit();
}
catch(HibernateException he) {
he.printPartialStackTrace(myWriter);
return;
}
myWriter.println("size after: " + loadedClaim.getDownsides().size());
Claim sameClaim = mcf.findClaim("152967");
myWriter.println("size after query: " + sameClaim.getDownsides().size());
All I'm doing in this test is pulling a claim out of the database, displaying the downsides, saving it with the database (which in this case is kind of pointless but I wanted to see what happened), and then checking the downsides again. I've been able to determine that if the Rationale member of the Downside object is NULL, the save adds a new Downside for that.
How can I configure my mapping file to fix this? There are some cases where the Rationale will be null, and I don't understand why this is causing Hibernate to generate new Downsides. Another thing: I'm still learning about hibernate, but why is it that loadedClaim.getDownsides.size() and sameClaim.getDownsides.size() give me different values? Does
Hibernate version: 2.1.6
Mapping documents:Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="linkup.objects.common.Claim" table="Claims" mutable="true" polymorphism="explicit">
<meta attribute="class-description">
The claim Object, including the derived class ProjectClaim.
@author AndrewJ
</meta>
<id name="id" column="id" type="long" unsaved-value="0">
<generator class="increment"/>
</id>
<property name="title" column="title" type="string"/>
<property name="description" column="description" type="string"/>
<property name="issues" column="issues" type="string"/>
<property name="theory" column="theory" type="string"/>
<many-to-one name="claimScenario"
class="linkup.objects.design.Scenario"
column="claimScenario"
cascade="save-update">
</many-to-one>
<property name="i" column="i" type="double"/>
<property name="r" column="r" type="double"/>
<property name="c" column="c" type="double"/>
<property name="draft" column="draft" type="boolean"/>
<property name="creationDate" column="dateCreated" type="timestamp"/>
<many-to-one name="primaryAttachment" class="linkup.objects.common.Attachment" cascade="none" />
<set name="upsides" table="Upsides" cascade="save-update">
<key column="claim"/>
<composite-element class="linkup.objects.design.Upside">
<many-to-one name="rationale" class="linkup.objects.design.Rationale" cascade="all"/>
<property name="upside" type="string"/>
</composite-element>
</set>
<set name="downsides" table="Downsides" cascade="save-update">
<key column="claim"/>
<composite-element class="linkup.objects.design.Downside">
<many-to-one name="rationale" class="linkup.objects.design.Rationale" cascade="all"/>
<property name="downside" type="string"/>
</composite-element>
</set>
<set name="primaryTasks" table="PrimaryTask_Claim">
<key column="claim"/>
<many-to-many
class="linkup.objects.common.PrimaryTask"
column="primaryTask">
</many-to-many>
</set>
<set name="tasks" table="NotificationTask_Claim">
<key column="claim"/>
<many-to-many
class="linkup.objects.common.Task"
column="notificationTask">
</many-to-many>
</set>
<set name="designAbstractions" table="DesignAbstraction_Claim">
<key column="claim"/>
<many-to-many
class="linkup.objects.common.DesignAbstraction"
column="designAbstraction">
</many-to-many>
</set>
<set name="attachments" table="Attachment_Claim">
<key column="claim"/>
<many-to-many column="attachment" class="linkup.objects.common.Attachment" />
</set>
<map name="relatedClaims"
table="Claim_Claim"
lazy="true">
<key column="claim1"/>
<index-many-to-many class="linkup.objects.common.Claim" column="claim2"/>
<element type="int" column="relationshipType"/>
</map>
<many-to-one name="author" class="linkup.objects.common.Author" />
<joined-subclass name="linkup.objects.design.ProjectClaim" table="ProjectClaims">
<meta attribute="class-description">
The derived class of a Claim limited to a single project
holds relationships to other Claims of possibly many types
@author AndrewJ
</meta>
<key column="derivedFromClaim"/>
<property name="system" type="long"/>
<property name="stage" type="java.lang.Integer"/>
<many-to-one name="projectScenario" class="linkup.objects.design.ProjectScenario"/>
<map name="relatedProjectClaims"
table="ProjectClaim_ProjectClaim"
lazy="true">
<key column="projectClaim1"/>
<index-many-to-many class="linkup.objects.design.ProjectClaim" column="projectClaim2"/>
<element type="string" column="type"/>
</map>
</joined-subclass>
</class>
</hibernate-mapping>
Name and version of the database you are using:
MySQL 4.0.11
The generated SQL (show_sql=true):
Quote:
Hibernate: update Claims set title=?, description=?, issues=?, theory=?, claimScenario=?, i=?, r=?, c=?, draft=?, dateCreated=?, primaryAttachment=?, author=? where id=?
Hibernate: update Scenarios set name=?, description=?, creationDate=? where id=?
Hibernate: delete from Downsides where claim=? and rationale=? and downside=?
Hibernate: insert into Downsides (claim, rationale, downside) values (?, ?, ?)
Hibernate: select claim0_.id as id6_, case when claim0__1_.derivedFromClaim is not null then 1 when claim0_.id is not null then 0 end as clazz_6_, claim0_.title as title20_6_, claim0_.description as descript3_20_6_, claim0_.issues as issues20_6_, claim0_.theory as theory20_6_, claim0_.claimScenario as claimSce6_20_6_, claim0_.i as i20_6_, claim0_.r as r20_6_, claim0_.c as c20_6_, claim0_.draft as draft20_6_, claim0_.dateCreated as dateCre11_20_6_, claim0_.primaryAttachment as primary12_20_6_, claim0_.author as author20_6_, claim0__1_.system as system28_6_, claim0__1_.stage as stage28_6_, claim0__1_.projectScenario as projectS4_28_6_, scenario1_.id as id0_, case when scenario1__1_.derivedFromScenario is not null then 1 when scenario1_.id is not null then 0 end as clazz_0_, scenario1_.name as name18_0_, scenario1_.description as descript3_18_0_, scenario1_.creationDate as creation4_18_0_, scenario1__1_.type as type19_0_, scenario1__1_.version as version19_0_, scenario1__1_.PScreationDate as PScreati4_19_0_, scenario1__1_.rationale as rationale19_0_, rationale2_.id as id1_, rationale2_.title as title1_, rationale2_.description as descript3_1_, rationale2_.timestamp as timestamp1_, rationale2_.urls as urls1_, rationale2_.published as published1_, rationale2_.results as results1_, attachment3_.id as id2_, attachment3_.name as name2_, attachment3_.description as descript3_2_, attachment3_.contentType as contentT4_2_, attachment3_.content as content2_, author4_.id as id3_, author4_.name as name3_, author4_.biography as biography3_, author4_.email as email3_, author4_.homepage as homepage3_, author4_.designerId as designerId3_, author4_.experience as experience3_, projectsce5_.derivedFromScenario as id4_, projectsce5_.type as type19_4_, projectsce5_.version as version19_4_, projectsce5_.PScreationDate as PScreati4_19_4_, projectsce5_.rationale as rationale19_4_, projectsce5__1_.name as name18_4_, projectsce5__1_.description as descript3_18_4_, projectsce5__1_.creationDate as creation4_18_4_, rationale6_.id as id5_, rationale6_.title as title5_, rationale6_.description as descript3_5_, rationale6_.timestamp as timestamp5_, rationale6_.urls as urls5_, rationale6_.published as published5_, rationale6_.results as results5_ from Claims claim0_ left outer join ProjectClaims claim0__1_ on claim0_.id=claim0__1_.derivedFromClaim left outer join Scenarios scenario1_ on claim0_.claimScenario=scenario1_.id left outer join ProjectScenarios scenario1__1_ on scenario1_.id=scenario1__1_.derivedFromScenario left outer join Rationales rationale2_ on scenario1__1_.rationale=rationale2_.id left outer join Attachments attachment3_ on claim0_.primaryAttachment=attachment3_.id left outer join Authors author4_ on claim0_.author=author4_.id left outer join ProjectScenarios projectsce5_ on claim0__1_.projectScenario=projectsce5_.derivedFromScenario left outer join Scenarios projectsce5__1_ on projectsce5_.derivedFromScenario=projectsce5__1_.id left outer join Rationales rationale6_ on projectsce5_.rationale=rationale6_.id where claim0_.id=?
Hibernate: select attachment0_.claim as claim__, attachment0_.attachment as attachment__, attachment1_.id as id0_, attachment1_.name as name0_, attachment1_.description as descript3_0_, attachment1_.contentType as contentT4_0_, attachment1_.content as content0_ from Attachment_Claim attachment0_ inner join Attachments attachment1_ on attachment0_.attachment=attachment1_.id where attachment0_.claim=?
Hibernate: select designabst0_.claim as claim__, designabst0_.designAbstraction as designAb2___, designabst1_.id as id0_, designabst1_.name as name0_, designabst1_.description as descript3_0_ from DesignAbstraction_Claim designabst0_ inner join DesignAbstractions designabst1_ on designabst0_.designAbstraction=designabst1_.id where designabst0_.claim=?
Hibernate: select tasks0_.claim as claim__, tasks0_.notificationTask as notifica2___, task1_.id as id0_, task1_.name as name0_, task1_.description as descript3_0_ from NotificationTask_Claim tasks0_ inner join NotificationTasks task1_ on tasks0_.notificationTask=task1_.id where tasks0_.claim=?
Hibernate: select primarytas0_.claim as claim__, primarytas0_.primaryTask as primaryT2___, primarytas1_.id as id0_, primarytas1_.name as name0_, primarytas1_.description as descript3_0_ from PrimaryTask_Claim primarytas0_ inner join PrimaryTasks primarytas1_ on primarytas0_.primaryTask=primarytas1_.id where primarytas0_.claim=?
Hibernate: select downsides0_.claim as claim__, downsides0_.rationale as rationale__, downsides0_.downside as downside__, rationale1_.id as id0_, rationale1_.title as title0_, rationale1_.description as descript3_0_, rationale1_.timestamp as timestamp0_, rationale1_.urls as urls0_, rationale1_.published as published0_, rationale1_.results as results0_ from Downsides downsides0_ left outer join Rationales rationale1_ on downsides0_.rationale=rationale1_.id where downsides0_.claim=?
Hibernate: select upsides0_.claim as claim__, upsides0_.rationale as rationale__, upsides0_.upside as upside__, rationale1_.id as id0_, rationale1_.title as title0_, rationale1_.description as descript3_0_, rationale1_.timestamp as timestamp0_, rationale1_.urls as urls0_, rationale1_.published as published0_, rationale1_.results as results0_ from Upsides upsides0_ left outer join Rationales rationale1_ on upsides0_.rationale=rationale1_.id where upsides0_.claim=?