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:
| Field | Usage |
|---|---|
| FKEY | person's primary key |
| FLASTNAME | person's last name |
| FFIRSTNAME | person's first name |
Database Table TADDRESS:
| Field | Usage |
|---|---|
| FKEY | address primary key |
| FSTREET | address street name |
| FCITY | address city name |
| FPERSONKEY | person'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:
| Extension | Description | Default value |
|---|---|---|
| result-type | the 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-type | the type of an element in an array (this will only be considered if the mapping type is array ) | automatic detection |
| allow-null | See chapter "Optional Relations". | false |
| cascade-delete | See chapter "Cascade Delete" | false |
| order-by | indicates how to order the results, the value looks like: "city ascending" | no |
| reference | extension that encloses the settings for a reference | a reference with default values |
| inverse | the inverse attribute for bidirectional relations | - |
| reverse-relation | marks as reverse relation in a bidirectional mapping | false |
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());
}
...
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>