One-To-Many Relation Mapping

This kind of relationship is an extension of one-to-one relations. You should understand the concepts behind one-to-one relations before reading this chapter.

Using one-to-many relations, you cannot only model a reference to a single object of same or different type, but as many references as you like.

The table structure is similar to the sample for the one-to-one-relation. But there is an foreign key in the address, that states which address belongs to which person. That means a person can have multiple addresses now, but every address belongs to exactly one person.

So the table structure looks like this:

Database Table TPERSON:

FieldUsage
FKEYperson's primary key
FLASTNAMEperson's last name
FFIRSTNAMEperson's first name

Database Table TADDRESS:

FieldUsage
FKEYaddress primary key
FSTREETaddress street name
FCITYaddress city name
FPERSONKEYperson's primary key

The class Person has to be able to store not only a single reference to the address but any number of addresses. This is normally done using a Collection implementation. The class Person could be implemented like that:

public class Person
{
  private Integer key;
  private String lastName;
  private String firstName;
  private List addr;
  ...

  public List getAddresses()
  {
    return addr;
  }
}
In this example all addresses are stored in a list (interface java.util.List ). A possible implementation for this interface is the class ArrayList.

There are no changes within the class Address .

The changes in type and back reference behaviour of attribute addr have to be reflected in the mapping descriptors. The attribute is now defined as a Collection . Other options would be Array and Map . For every Collection the element type, i.e. the type of the elements stored within the Collection , must be defined. In the example all objects inside the Collection are of type Address .

The relationship between the classes and the tables is defined in the mapping-extension of this field with the value " one-to-many ". Potential nested extensions of this mapping are:

ExtensionDescriptionDefault value
result-typethe type of the element in the object field (mostly an implementation that can manage a list of objects)depending on the mapping type
( collection,map, array ): java.util.ArrayList,
java.util.HashMap
, typed Array
element-typethe type of an element in an array (this will only be considered if the mapping type is array )automatic detection
allow-nullSee chapter "Optional Relations".false
cascade-deleteSee chapter "Cascade Delete"false
order-byindicates how to order the results, the value looks like: "city ascending"no
referenceextension that encloses the settings for a referencea reference with default values
inversethe inverse attribute for bidirectional relations-
reverse-relationmarks as reverse relation in a bidirectional mappingfalse

The modified result type ( result-type element) tells Signsoft intelliBO which implementation of the Collection interface is used and enables dynamic creation of the resulting collection object. We suggest, always creating a new instance of type ArrayList inside the Person 's constructor, even if there are no referenced objects.

As you can see, table relations are again defined in Signsoft intelliBO using the nested extension reference in the mapping. The herein used extensions are the same as in the one-to-one mapping.

The JDO file of the Person now looks like this:

<class name="Person" ...>
  ...
  <field name="key" ...>...
  <field name="lastName"...>....
  <field name="firstName"...>....

  <field name="addr">
    <collection element-type="com.test.Address"/>
    <extension vendor-name="ssibo" key="jdbc">
      <extension vendor-name="ssibo" key="mapping" value="one-to-many">
        <extension vendor-name="ssibo" key="result-type" value="java.util.ArrayList"/>
        <extension vendor-name="ssibo" key="cascade-delete" value="true"/>
        <extension vendor-name="ssibo" key="reference">
          <extension vendor-name="ssibo" key="src-table" value="TPERSON"/>
          <extension vendor-name="ssibo" key="src-field" value="FKEY"/>
          <extension vendor-name="ssibo" key="dst-table" value="TADDRESS"/>
          <extension vendor-name="ssibo" key="dst-field" value="FPERSONKEY"/>
        </extension>
      </extension>
    </extension>
  </field>

</class>

Use the list at runtime as you would do without Signsoft intelliBO:

//Creating a person with two addresses

Person p = new Person();
p.setLastName("Smith");
pm.makePersitent(p);

Address a1 = new Address();
a1.setCity("New York");
p.getAddresses.add(a1);

Address a2 = new Address();
a2.setCity("Boston");
p.getAddresses.add(a2);

...

// Reading the addresses of the person
List list = p.getAddresses();
for (int i = 0; i < list.size(); i++)
{
  Address a = (Address) list.get(i);
  System.out.println(a.getCity());
}
...

Bidirectional Relation

An one-to-many bidirectional relation is modelled with two relations. A one-to-many relation for the reference from class A to a collection of class B and an one-to-one relation from the class B to the class A. Just as for one-to-one bidirectional relations, the inverse element can be set to the reverse referencing attribute (here: owner of class Address ).

<?xml version="1.0" encoding="UTF-8"?>
<jdo xmlns="http://java.sun.com/xml/ns/jdo/jdo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/jdo/jdo http://java.sun.com/xml/ns/jdo/jdo_2_0.xsd">

  <package name="com.signsoft.ibo.sample">
    <class name="Person">
      <field name="addr">
        <collection element-type="com.signsoft.ibo.sample.Address"/>
        <extension key="jdbc" vendor-name="ssibo">
          <extension key="mapping" value="one-to-many" vendor-name="ssibo">
            <extension key="result-type" value="java.util.ArrayList" vendor-name="ssibo"/>
            <extension key="element-type" value="com.signsoft.ibo.sample.Address"
                                                              vendor-name="ssibo"/>
       <!-- inverse field in class Address -->
            <extension key="inverse" value="owner" vendor-name="ssibo"/>
            <extension key="reference" vendor-name="ssibo">
              <extension key="src-table" value="TPERSON" vendor-name="ssibo"/>
              <extension key="src-field" value="IBOXFID" vendor-name="ssibo"/>
              <extension key="dst-table" value="TADDRESS" vendor-name="ssibo"/>
              <extension key="dst-field" value="FPERSONID" vendor-name="ssibo"/>
            </extension>
          </extension>
        </extension>
      </field>
    </class>
  </package>
</jdo>