Meaningless Drivel is fun!*
The moose likes Object Relational Mapping and the fly likes Ternary and composite ID Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Databases » Object Relational Mapping
Bookmark "Ternary and composite ID" Watch "Ternary and composite ID" New topic
Author

Ternary and composite ID

Lilly Wiesie
Greenhorn

Joined: Jan 20, 2005
Posts: 26
I am working on ternary relationship using composite ID:

Table TernayA - PK: TernaryAID
Table TernaryB - PK: TernaryBID
Table TernaryC - PK: TernaryCID
Table TernaryAll - composite key: TernaryAID, TernaryBID, TernaryCID (which maps to the PK in tables TernarA, TernaryB, and TernaryC).

Here are the mapping files:

TernaryA.hbm.xml
----------------
<?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.tietronix.hbn.dal.TernaryA"
table="TernaryA"
dynamic-update="true"
dynamic-insert="true"
select-before-update="true"
>

<id
name="ternaryAid"
type="java.lang.Integer"
column="TernaryAID"
unsaved-value="0"
>
<generator class="identity" />
</id>

<property
name="ternaryAdesc"
type="java.lang.String"
column="TernaryADesc"
length="50"
/>

<!-- Associations -->

<!-- bi-directional one-to-many association to TernaryAll -->
<set
name="ternaryAlls"
lazy="true"
inverse="true"
cascade="all"
>
<key>
<column name="TernaryAID" />
</key>
<one-to-many
class="com.tietronix.hbn.dal.TernaryAll"
/>
</set>

</class>
</hibernate-mapping>

========================================================================

TernaryB.hbm.xml:
-----------------
<?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.tietronix.hbn.dal.TernaryB"
table="TernaryB"
dynamic-update="true"
dynamic-insert="true"
select-before-update="true"
>

<id
name="ternaryBid"
type="java.lang.Integer"
column="TernaryBID"
unsaved-value="0"
>
<generator class="identity" />
</id>

<property
name="ternaryBdesc"
type="java.lang.String"
column="TernaryBDesc"
length="50"
/>

<!-- Associations -->

<!-- bi-directional one-to-many association to TernaryAll -->
<set
name="ternaryAlls"
lazy="true"
inverse="true"
cascade="all"
>
<key>
<column name="TernaryBID" />
</key>
<one-to-many
class="com.tietronix.hbn.dal.TernaryAll"
/>
</set>

</class>
</hibernate-mapping>

============================================================

TerberyC.hbm.xml:
-----------------
<?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.tietronix.hbn.dal.TernaryC"
table="TernaryC"
dynamic-update="true"
dynamic-insert="true"
select-before-update="true"
>

<id
name="ternaryCid"
type="java.lang.Integer"
column="TernaryCID"
unsaved-value="0"
>
<generator class="identity" />
</id>

<property
name="ternaryCdesc"
type="java.lang.String"
column="TernaryCDesc"
length="50"
/>

<!-- Associations -->

<!-- bi-directional one-to-many association to TernaryAll -->
<set
name="ternaryAlls"
lazy="true"
inverse="true"
cascade="all"
>
<key>
<column name="TernaryBID" />
</key>
<one-to-many
class="com.tietronix.hbn.dal.TernaryAll"
/>
</set>

</class>
</hibernate-mapping>

======================================================

TernaryAll.hbm.xml:
-------------------
<?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.tietronix.hbn.dal.TernaryAll"
table="TernaryAll"
>

<composite-id>
<key-property
name="ternaryAid"
column="TernaryAID"
type="int"
length="10"
/>
<key-property
name="ternaryBid"
column="TernaryBID"
type="int"
length="10"
/>
<key-property
name="ternaryCid"
column="TernaryCID"
type="int"
length="10"
/>
</composite-id>
<many-to-one
name="ternaryA"
cascade="all"
class="com.tietronix.hbn.dal.TernaryA"
not-null="true"
insert="false"
update="false"
>
<column name="TernaryAID" />
</many-to-one>
<many-to-one
name="ternaryB"
cascade="all"
class="com.tietronix.hbn.dal.TernaryB"
not-null="true"
insert="false"
update="false"
>
<column name="TernaryBID" />
</many-to-one>
<many-to-one
name="ternaryC"
cascade="all"
class="com.tietronix.hbn.dal.TernaryC"
not-null="true"
insert="false"
update="false"
>
<column name="TernaryCID" />
</many-to-one>

</class>
</hibernate-mapping>

===============================================

Here is the testing jsp:

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@page import="org.hibernate.*"%>
<%@page import="com.tietronix.hbn.dal.*"%>
<%@page import="com.tietronix.hbn.util.*"%>
<%@page import="java.util.*"%>

<html>
<head><title>JSP Page</title></head>
<body>
<%
org.hibernate.Session session2 = hbnUtil.currentSession();

Transaction tx = session2.beginTransaction();

TernaryA tbA = new TernaryA();
tbA.setTernaryAdesc("John");

TernaryB tbB = new TernaryB();
tbB.setTernaryBdesc("Tomato Juice");

TernaryC tbC = new TernaryC();
tbC.setTernaryCdesc("too much");

TernaryAll tbAll = new TernaryAll();

Set mSet = new HashSet();
mSet.add ( tbAll );

tbA.setTernaryAlls( mSet );
tbB.setTernaryAlls( mSet );
tbC.setTernaryAlls( mSet );

tbAll.setTernaryA( tbA );
tbAll.setTernaryB( tbB );
tbAll.setTernaryC(tbC);

session2.save(tbA);
session2.save( tbB );
session2.save( tbC );
session2.flush();
tx.commit();

hbnUtil.closeSession();
%>
Test completed
</body>
</html>

The records did get saved for TernaryA, TernaryB, and TernaryC. But nothing was saved in table TernaryAll, did I miss something?

Also what will be a better way to handle ternary relationship in Hibernate? I actually have a table that has a composite key containing four columns (three as foreign keys, and the last one is some assigned value).

Thanks.

Lilly
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
The only thing that looks suspect to me is giving the A, B and C objects the same Set of TernaryAlls. It probably doesn't make a difference in this case since you're just creating and saving the objects, but it will cause issues later if you have continue adding more objects or use a second-level cache. For example, if you added a new TernaryAll that linked to TernaryA and two new TernaryB and TernaryC instances, the original TernaryB and TernaryC would get the new TernaryAll added to their Set since it's the same Set that TernaryA has.

I only know that the Hibernate developers will tell you again and again not to use composite IDs, and I can say from a database and general ORM point-of-view that they are a major PITA. If you can create a surrogate key for that table, it will be much easier.

Okay, reading the Hibernate mapping docs for composite-id I notice that it says there are two types of columns: key-property and key-many-to-one. Have you tried using the latter as it seems to be what you'd want?

As for more information on ternary (and more) associations, the Hibernate docs briefly mention ternary associations.
Lilly Miaqa
Greenhorn

Joined: Jan 25, 2005
Posts: 8
Dave,

Thanks.

Looks like I need to search alternative ways to implement the ternary relationship.

That's a good advice on not using the composite key. I'll keep it in mind.

Lilly
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Ternary and composite ID