Declarative Objectivity (DO) Language : Attribute Structures : Reference Attributes
Reference Attributes
Reference attributes are attributes that can hold references to persistent instances of a referenceable schema class.
   =
Reference Values
Logical Type
Settings
Options
Quick Look
Unidirectional references
 
Reference
Referenced:
referenceableClass
currentRental: Reference {
  Referenced: FleetData.RentalContract
}
Bidirectional references
 
Reference
Referenced:
referenceableClass
atStall: Reference {
  Referenced: FleetData.Stall,
  Inverse: occupiedBy
}
Inverse
attributeName
 
Discussion 
For general syntax information, see About Attribute Structures.
A reference is a value that refers to an existing persistent object that is stored in a federated database. A reference encapsulates the object identifier (OID) that uniquely identifies a persistent object of a particular schema class in a federated database. For examples of literal reference values, see Literal Expressions.
A reference attribute is an attribute for holding a single reference to an object. You use reference attributes to model to-one relationships, also called a to-one UML association. (You use a collection attribute to model a to-many relationship.)
References can be unidirectional or bidirectional:
An attribute holding a unidirectional reference represents a unidirectional relationship, which supports one-way traversal from one object to another.
An attribute holding a bidirectional reference is always paired with a second such attribute; together they represent a bidirectional relationship, which supports two-way traversal between a pair of objects.
A reference attribute can be empty—for example, if it was never set or if it has been cleared. In effect, such an attribute holds a null reference value, which is displayed as 0-0-0-0.
Specifying the Attribute Type
A reference attribute has the following logical type:
Logical Type
Description
Reference
References (encapsulated OIDs) to persistent instances of a referenceable schema class.
 
Specifying Type Characteristics
A reference attribute uses the following settings to specify detailed type characteristics:
Setting
Specifies
Referenced:
The namespace-qualified name of the class of the objects to be referenced. Must be a referenceable schema class.
Inverse:
The name of the attribute within the referenced class that will hold the inverse in a pair of bidirectional references.
Note:For clarity, you typically include the Inverse: setting in the structures for both attributes that will hold a coordinated pair of bidirectional references. For convenience, you can omit this setting from the either of the two attribute structures, and allow the inverse to be inferred from the other structure. The Inverse setting is displayed in both attributes if you show the classes.
About References
A reference is a value that refers to an existing persistent object in a federated database. A reference encapsulates the object identifier (OID) that uniquely identifies a persistent object in a federated database.
References support reference semantics, which means multiple objects can link to and share the same object. For example, assume that multiple vehicles can be rented on a single rental contract. You can represent this by setting a reference attribute in each of the rented Vehicle objects with a reference that identifies the same RentalContract object. (Each Vehicle object stores a separate copy of the reference.)
References enforce strong typing, which means that you can assign a reference to a reference attribute only if the reference is of the correct type. A reference is of the correct type if it points to an object of the schema class specified in the Referenced: setting or to an object of a subclass of the referenced class. An error occurs if you try to assign a reference of an incorrect type. For example, assume a Vehicle has an attribute for storing a reference to a RentalContract object. If the RentalContract class has a subclass called LeaseContract, you could use the attribute to link a Vehicle to a RentalContract object or to a LeaseContract object. However, the attribute cannot be used to link a Vehicle to an object of class Customer, which is not a subclass of RentalContract.
A reference is valid if it encapsulates an OID that identifies an existing object in the federated database. It is possible to for references to become invalid. For example, assume that a Vehicle object has a reference attribute that holds a reference to a particular RentalContract object. If you delete that RentalContract object without clearing the reference attribute first, the reference held by the Vehicle object now points to no existing object, and so is invalid. (You can avoid this by using bidirectional references, which cause reference attributes to be cleared automatically when destination objects are deleted.)
About Unidirectional References
A unidirectional reference is a reference value that represents a one-way relationship between an object of a source class and an object of a destination class.
The source class defines an attribute for holding either a single unidirectional reference or a collection of such references. Furthermore:
The source class may be either referenceable or embeddable.
The destination class must be referenceable, and may be the same as the source class. The destination class is specified by the Referenced: setting of the attribute structure.
When a source class defines a reference attribute for unidirectional references, you can use that attribute to link a particular object of the source class to a particular object of the destination class. The reference implementing the link is stored as the attribute’s value in the source object. The stored reference encapsulates the object identifier (OID) of the destination object. Because an OID uniquely identifies the object by its location within the federated database, a DO query can use the reference to traverse from the source object to the destination object.
Example. The following UPDATE SCHEMA statement creates two related schema classes, Vehicle and RentalContract. Vehicle is the source class, with a unidirectional reference attribute called currentRental for referencing an object of RentalContract, the destination class:
UPDATE SCHEMA 
{
  CREATE CLASS FleetData.Vehicle 
  {
    ...
    currentRental: Reference {
      Referenced: FleetData.RentalContract
    },
    ...
  }
 
  CREATE CLASS FleetData.RentalContract 
  {
    ...
  }
}
The currentRental attribute enables you to link a particular Vehicle object to a related RentalContract object. Within the Vehicle object, the currentRental attribute value is a unidirectional reference containing the RentalContract’s OID, as shown in the following diagram:
A DO query that finds a particular Vehicle object can use the stored OID to find and access the related RentalContract object:
FROM Vehicle RETURN currentRental.trackingNumber;
Bidirectional References
A bidirectional reference is a reference value that can combine with another bidirectional reference to support a two-way relationship between a pair of objects. When two objects are bidirectionally related, each of these objects has an attribute that references the other. Updating the attribute in one object automatically updates the corresponding attribute in the other.
A bidirectional reference never occurs alone, but is always part of a coordinated pair. Considered by itself, each bidirectional reference within the pair enables an object of a source class to refer to an object of a destination class. Within a pair of such references, the source class of either reference is also the destination class of the other. Put another way, each bidirectional reference in the pair serves as the inverse of the other.
You model a bidirectional relationship between two classes by defining a coordinated pair of inverse attributes. Each such attribute is defined in a source class, and references a destination class. Each attribute may hold a single reference (to-one) or a collection of references (to-many). Furthermore:
A source class must be referenceable.
The destination class must be referenceable, and may be the same as the source class. The destination class is specified by the Referenced: setting of the attribute structure.
The destination class must have an attribute for holding bidirectional references to objects of the source class. This attribute is specified by the Inverse: setting of the attribute structure.
When two classes have inverse attributes, you can use those attributes to link an object of one class to an object of the other class. Doing so automatically creates an inverse link from the second object to the first. Each object stores a reference value encapsulating the object identifier (OID) of its destination object. Because an OID uniquely identifies an object by its location within the federated database, DO queries can use the pair of bidirectional references to traverse from each object to the other.
Example. The following UPDATE SCHEMA statement creates two referenceable schema classes, Vehicle and Stall, where each class has a bidirectional reference attribute to the other class. The Vehicle class’s atStall attribute looks for its inverse in the Stall class’s occupiedBy attribute, and vice versa.
UPDATE SCHEMA 
{
  CREATE CLASS FleetData.Vehicle 
  {
    ...
    atStall: Reference {
      Referenced: FleetData.Stall,
      Inverse: occupiedBy
    },
    ...
  }
 
  CREATE CLASS FleetData.Stall 
  {
    ...
    occupiedBy: Reference {
      Referenced: FleetData.Vehicle,
      Inverse: atStall
    },
    ...
  }
}
Note:For clarity, this example includes the Inverse: setting explicitly in both attribute definitions. For convenience, you can omit this setting from one of them, and DO will automatically insert it.
Note:For simplicity, this example shows how to define a bidirectional relationship between two newly created classes. See Adding Bidirectional Relationships for an example that defines a bidirectional relationship between two existing classes.
The atStall and occupiedBy attributes enable you to form a bidirectional link between a particular Vehicle object and a related Stall object. Setting the Vehicle’s atStall attribute automatically causes the Stall’s occupiedBy attribute to be set. Each object provides storage for a bidirectional reference containing the other object’s OID, as shown in the following diagram:
A DO query that finds a Vehicle object can use the OID stored in the atStall attribute to find and access the related Stall object.
FROM Vehicle RETURN atStall.number;
Conversely, a query that finds a Stall object can use the OID stored in the occupiedBy attribute to find and access the related Vehicle object.
FROM Stall RETURN vehicle.license;
Referential Integrity in Bidirectional Relationships
The federated database uses the inverse links to maintain referential integrity. If you delete one of two linked objects from the federated database, the linking value is automatically removed from the other object. This prevents the remaining object from storing an invalid (dangling) reference that points to no existing object.
Considerations for Choosing a Particular Directionality
In general, you choose the reference directionality that best supports your requirements. If two-way traversal is not required, you should consider using a unidirectional reference, which requires somewhat less overhead and offers better performance than bidirectional reference. However, unidirectional references do not automatically maintain referential integrity.
Note:If you choose to use unidirectional references, it is your responsibility to ensure that every such reference you store links to a valid destination object.