A very simple relation between two tables is an one-to-one relation. Using this relation, for every row in the first table exactly one other row in the second table is assigned. The relation is reflected in the object world using a reference to another object.
A person, for example, can have an address. Instead of adding the address attributes itself into the person they can be separated in a different class. The class Person then contains exactly one reference to an object of class Address .
Here is an example for such a Person class:
public class Person
{
private Integer key;
private String lastName;
private String firstName;
private Address addr;
...
public void setAddress(Address addr)
{
this.addr = addr;
}
public Address getAddress()
{
return addr;
}
}
At runtime, the attribute addr of class Person holds a reference to an object of class Address . If there is no address assigned to this person at the database layer, this reference contains the value null.
The Address referenced by the Person class could be implemented like that:
public class Address
{
private Integer key;
private String street;
private String city;
}
This relation corresponds to some table structure, for example:
Database Table TPERSON:
| Field | Usage |
|---|---|
| FKEY | person's primary key |
| FLASTNAME | person's last name |
| FFIRSTNAME | person's first name |
| FADDRKEY | person's foreign key for the address |
In this table you find a field for the primary key of a person's address in addition to the other fields of the Person itself.
Database Table TADDRESS:
| Field | Usage |
|---|---|
| FKEY | addresses' primary key |
| FSTREET | addresses' street name |
| FCITY | addresses' city name |
Now there must be a JDO file for both classes that defines the persistent fields. You can use separate files per class or one file for the whole package.
The mappings in the JDO file for the Address class are very simular to those described in the chapter "Direct field mapping". The attributes of the Person are also mapped with direct field-mappings accept the addr attribute. As you see, this attribute is treated like a normal persistent attribute. The relationship between the classes and the tables is defined in the mapping-extension of this field with the value " one-to-one ".
Potential nested extensions of this mapping are (with default values if no specified otherwise):
| Extension | Description | Default value |
|---|---|---|
| element-type | the type of the element in the object field | automatic detection |
| allow-null | See chapter "Optional Relations". | false |
| cascade-delete | See chapter "Cascade Delete" | false |
| reference | extension that encloses the settings for a reference | a reference with default values (see below) |
| inverse | the inverse attribute for bidirectional relations | - |
| reverse-relation | marks as reverse relation in a bidirectional mapping | false |
The nested reference extension defines the reference between the tables that participate on this relation. The following extensions can be used within a reference-extension:
| Extension | Description | Default value |
|---|---|---|
| src-table | the name of the table containing the referencing object | the table name defined for the class |
| src-field | the name of the field where the reference value is stored | extracted from field name using naming rules |
| dst-table | the name of the table containing the referenced object | extracted from field type name using naming rules |
| dst-field | the name of the field that contains the reference value that is used | extracted from field name using naming rules |
| sql-type | the SQL type (only necessary if the database is not able to provide the correct type) | automatic detection |
Please note: compound relations are defined by multiple reference extensions.
Sample JDO file for class Person and Address :
<class name="Person" ...>
...
<field name="key" primary-key="true">
<extension key="jdbc" vendor-name="ssibo">
<extension key="mapping" value="direct" vendor-name="ssibo">
<extension key="field-name" value="FKEY" vendor-name="ssibo"/>
<extension key="table-name" value="TPERSON" vendorname=" ssibo"/>
</extension>
</extension>
</field>
<field name="lastName"...>....
<field name="firstName"...>....
<field name="addr">
<extension vendor-name="ssibo" key="jdbc">
<extension vendor-name="ssibo" key="mapping" value="one-to-one">
<extension vendor-name="ssibo" key="element-type" value="com.signsoft.Address"/>
<extension vendor-name="ssibo" key="reference">
<extension vendor-name="ssibo" key="src-table" value="TPERSON"/>
<extension vendor-name="ssibo" key="src-field" value="FADDRKEY"/>
<extension vendor-name="ssibo" key="dst-table" value="TADDRESS"/>
<extension vendor-name="ssibo" key="dst-field" value="FKEY"/>
</extension>
</extension>
</extension>
</field>
</class>
<class name="Address" ...>
...
<field name="key" primary-key="true">
<extension key="jdbc" vendor-name="ssibo">
<extension key="mapping" value="direct" vendor-name="ssibo">
<extension key="field-name" value="FKEY" vendor-name="ssibo"/>
<extension key="table-name" value="TADDRESS" vendorname=" ssibo"/>
</extension>
</extension>
</field>
<field name="street"...>....
<field name="city"...>....
</class>
In this file the exact relation between the two tables is defined in XML. The relation between both tables is defined using a foreign key in the person's table, which is the primary key of class Address .
The relation between the two tables is declared using a reference extension. Such an extension describes, which fields of a table should be used to define a relationship to the other table. The fields in this relationship do not need to be persistent attributes of the class.
Additionally you should provide the element-type to help Signsoft intelliBO to create the referenced objects at run time. This type could be theoretically resolved at run time, but by explicitly stating the type you have the opportunity to use an interface as an attribute type. If you do that, Signsoft intelliBO always needs to know which concrete implementation shall be used.
In your application you can work with the attributes as you normally do in Java applications. We suggest, always using set - and get -methods for all attributes.
...
// Creating a person with an address
Person p = new Person();
p.setLastName("Smith");
pm.makePersistent(p);
Address a = new Address();
a.setCity("New York");
p.setAddress(a);
...
// Reading the address of a person
a = p.getAddress();
System.out.println(a.getCity());
...
An one-to-one bidirectional relation is modelled with two one-to-one relations: An one-to-one relation for the reference from class A to class B and an one-to-one relation from the class B to the class A. Additionally Signsoft intelliBO supports bidirectional relations with the element inverse , which specifies the reverse referencing attribute (in this sample, attribute owner of Address and addr of Person).
The relation from class B to class A has the same description as relation from class A to class B. To mark it as the reverse directed relation, extension reverse-relation can be set true .
<?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">
<extension key="jdbc" vendor-name="ssibo">
<extension key="mapping" value="one-to-one" vendor-name="ssibo">
<extension key="element-type" value="com.signsoft.ibo.sample.Address"
vendor-name="ssibo"/>
<!-- inverse element 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="FADDRESSID" vendor-name="ssibo"/>
<extension key="dst-table" value="TADDRESS" vendor-name="ssibo"/>
<extension key="dst-field" value="IBOXFID" vendor-name="ssibo"/>
</extension>
</extension>
</extension>
</field>
</class>
</package>
</jdo>
<?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="Address">
<field name="owner">
<extension key="jdbc" vendor-name="ssibo">
<extension key="mapping" value="one-to-one" vendor-name="ssibo">
<extension key="element-type" value="com.signsoft.ibo.sample.Person"
vendor-name="ssibo"/>
<!--reverse relation-->
<extension key="reverse-relation" value="true" vendor-name="ssibo"/>
<extension key="inverse" value="addr" vendor-name="ssibo"/>
<extension key="reference" vendor-name="ssibo">
<extension key="src-table" value="TPERSON" vendor-name="ssibo"/>
<extension key="src-field" value="FADDRESSID" vendor-name="ssibo"/>
<extension key="dst-table" value="TADDRESS" vendor-name="ssibo"/>
<extension key="dst-field" value="IBOXFID" vendor-name="ssibo"/>
</extension>
</extension>
</extension>
</field>
</class>
</package>
</jdo>