I'm posting again here because after reading and re-reading the manual, I don't understand how really works an association in hibernate.
I have an object tournament which is associated to a cupGroup and I tried 2 different cases to understand.
1. I used exactly the mapping files below and it worked.
2. I replaced in the tournament mapping file the all-delete-orphan for the CupGroup class by none that led to an exception.
This makes me ask a question : what is the interest of the cascade attribute if the two objects of the relationship are not persistent.
I thought the cascade attribute allowed us to save at the same time all the objects of the relationship.
If I'm correct the cascade attribute allows us to save an object B from its related object A of the relationship without saving explicitly the object B.
Am I right ?
I hope you will understand what I meant.
Stack Exception
net.sf.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.pescorer.business.CupGroup
at net.sf.hibernate.impl.SessionImpl.throwTransientObjectException(SessionImpl.java:2768)
at net.sf.hibernate.impl.SessionImpl.getEntityIdentifierIfNotUnsaved(SessionImpl.java:2760)
at net.sf.hibernate.type.EntityType.getIdentifier(EntityType.java:66)
at net.sf.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:47)
at net.sf.hibernate.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:384)
at net.sf.hibernate.collection.Set.writeTo(Set.java:226)
at net.sf.hibernate.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:523)
at net.sf.hibernate.impl.ScheduledCollectionRecreate.execute(ScheduledCollectionRecreate.java:23)
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2418)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2375)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2240)
at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
at com.pescorer.business.base._BaseRootDAO.commitTransaction(_BaseRootDAO.java:200)
at com.pescorer.business.base._BaseRootDAO.save(_BaseRootDAO.java:606)
at com.pescorer.business.base.BaseTournamentDAO.save(BaseTournamentDAO.java:60)
at com.pescorer.business.TournamentTest.testGetSetOption(TournamentTest.java:89)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:421)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:305)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:186)
Here is the code :
Code:
OptionDAO dao = OptionDAO.getInstance();
Option option0 = dao.load(new Integer(0));
Tournament tournament = new Tournament();
tournament.setName("bla");
tournament.setNormalMode(true);
tournament.setTournamentType(TournamentType.CUP);
tournament.setOrganizer("tutu");
tournament.setDate(new Date(Calendar.getInstance().getTimeInMillis()));
tournament.setFinished(false);
tournament.addToOptions(option0);
TournamentDAO tournamentDao = TournamentDAO.getInstance();
Integer id = tournamentDao.save(tournament);
CupGroup gr = new CupGroup();
gr.setTournamentId(id);
tournament.addToCupGroups(gr);
tournamentDao.save(tournament);
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>
<!--
Created by the Middlegen Hibernate plugin 2.1
http://boss.bekk.no/boss/middlegen/
http://www.hibernate.org/
-->
<class
name="com.pescorer.business.Tournament"
table="TOURNAMENT"
>
<id
name="id"
type="java.lang.Integer"
column="ID"
>
<generator class="native" />
</id>
<property
name="name"
type="java.lang.String"
column="NAME"
not-null="true"
length="100"
/>
<property
name="normalMode"
type="boolean"
column="NORMAL_MODE"
not-null="true"
/>
<property
name="organizer"
type="java.lang.String"
column="ORGANIZER"
not-null="true"
length="50"
/>
<property
name="date"
type="java.sql.Date"
column="DATE"
not-null="true"
/>
<property
name="place"
type="java.lang.String"
column="PLACE"
length="50"
/>
<property
name="logo"
type="java.lang.String"
column="LOGO"
length="255"
/>
<property
name="finished"
type="boolean"
column="FINISHED"
not-null="true"
/>
<!-- Associations -->
<!-- uni-directional one-to-many association to GroupGame -->
<set
name="groupGames"
lazy="true"
cascade="none"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<one-to-many
class="com.pescorer.business.GroupGame"
/>
</set>
<!-- uni-directional one-to-many association to DoubleOption -->
<set
name="doubleOptions"
lazy="true"
cascade="none"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<one-to-many
class="com.pescorer.business.DoubleOption"
/>
</set>
<!-- uni-directional one-to-many association to CupGroup -->
<set
name="cupGroups"
lazy="true"
cascade="all-delete-orphan"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<one-to-many
class="com.pescorer.business.CupGroup"
/>
</set>
<!-- uni-directional one-to-many association to BestDefense -->
<set
name="bestDefenses"
lazy="true"
cascade="none"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<one-to-many
class="com.pescorer.business.BestDefense"
/>
</set>
<!-- uni-directional one-to-many association to ChampionshipGeneralStanding -->
<set
name="championshipGeneralStandings"
lazy="true"
cascade="none"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<one-to-many
class="com.pescorer.business.ChampionshipGeneralStanding"
/>
</set>
<!-- uni-directional one-to-many association to ChampionshipGame -->
<set
name="championshipGames"
lazy="true"
cascade="none"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<one-to-many
class="com.pescorer.business.ChampionshipGame"
/>
</set>
<!-- uni-directional one-to-many association to IntOption -->
<set
name="intOptions"
lazy="true"
cascade="none"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<one-to-many
class="com.pescorer.business.IntOption"
/>
</set>
<!-- uni-directional one-to-many association to BestAttack -->
<set
name="bestAttacks"
lazy="true"
cascade="none"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<one-to-many
class="com.pescorer.business.BestAttack"
/>
</set>
<!-- uni-directional one-to-many association to CupGame -->
<set
name="cupGames"
lazy="true"
cascade="none"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<one-to-many
class="com.pescorer.business.CupGame"
/>
</set>
<!-- uni-directional one-to-many association to BoolOption -->
<set
name="boolOptions"
lazy="true"
cascade="none"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<one-to-many
class="com.pescorer.business.BoolOption"
/>
</set>
<!-- uni-directional many-to-one association to TournamentType -->
<many-to-one
name="tournamentType"
class="com.pescorer.business.TournamentType"
>
<column name="TYPE_ID" />
</many-to-one>
<!-- uni-directional many-to-many association to User -->
<set
name="users"
lazy="true"
cascade="none"
table="TOURNAMENT_USERS"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<many-to-many
class="com.pescorer.business.User"
>
<column name="USER_ID" />
</many-to-many>
</set>
<!-- uni-directional many-to-many association to Federation -->
<set
name="federations"
lazy="true"
cascade="none"
table="TOURNAMENT_FEDERATIONS"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<many-to-many
class="com.pescorer.business.Federation"
>
<column name="FEDERATION_ID" />
</many-to-many>
</set>
<!-- uni-directional many-to-many association to Option -->
<set
name="options"
lazy="true"
cascade="none"
table="TOURNAMENT_OPTIONS"
>
<key>
<column name="TOURNAMENT_ID" />
</key>
<many-to-many
class="com.pescorer.business.Option"
>
<column name="OPTION_ID" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
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>
<!--
Created by the Middlegen Hibernate plugin 2.1
http://boss.bekk.no/boss/middlegen/
http://www.hibernate.org/
-->
<class
name="com.pescorer.business.CupGroup"
table="CUP_GROUP"
>
<id
name="id"
type="java.lang.Integer"
column="ID"
>
<generator class="native" />
</id>
<!-- Associations -->
<!-- uni-directional one-to-many association to GroupGame -->
<set
name="groupGames"
lazy="true"
cascade="none"
>
<key>
<column name="GROUP_ID" />
</key>
<one-to-many
class="com.pescorer.business.GroupGame"
/>
</set>
<!-- uni-directional one-to-many association to GroupGeneralStanding -->
<set
name="groupGeneralStandings"
lazy="true"
cascade="none"
>
<key>
<column name="GROUP_ID" />
</key>
<one-to-many
class="com.pescorer.business.GroupGeneralStanding"
/>
</set>
<!-- uni-directional one-to-many association to GroupUser -->
<set
name="groupUsers"
lazy="true"
cascade="none"
>
<key>
<column name="GROUP_ID" />
</key>
<one-to-many
class="com.pescorer.business.GroupUser"
/>
</set>
<property
name="tournamentId"
column="TOURNAMENT_ID"
type="java.lang.Integer"
not-null="true"
/>
</class>
</hibernate-mapping>
Name and version of the database you are using:
HSQLDB 1.7.2