PriDE Design Patterns: Relationships


An entity resp. a database record usually doesn't stand by its own but is somehow related to other data. A customer has an address, an account has an owner, a car has four wheels and so on. In object-oriented systems these relationships are expressed by object references making up a navigatable tree or net structure of objects. Many O/R mapping tools and also the established standards JDO and EJB CMP (version 2.0) include transparent support of object relations. E.g. if there is a 1:1 relationship defined between a customer and his address, an expression like myCustomer.getAddress() is supposed to return an Address object. No programming should be required for that, and loading of the address record is performed on demand or as a join together with the rest of customer data or somehow else but somehow reasonable. Depending on the O/R mapper's capabilities or the standard it follows, it also supports cascade delete or ensures referencial intergrity if object relations are modified.

At first sight it may be shocking to hear that by default none of these features is supported by PriDE. However, on second sight it turns out that most of these capabilities can easiliy be implemented individually while being an unnessesary burden for any toolkit when proclaimed as a standard. The example of a customer and its address allows to demonstrate that. When using a canonical mapping of an 'addressable' customer, the corresponding entity in PriDE would e.g. look like this:

class Customer extends MappedObject {
    protected static RecordDescriptor red = new RecordDescriptor
        (Customer.class, "customer", null, new String[][] {
            { "id",      "getId",      "setId" },
            { "name",    "getName",    "setName" },
            { "address_key",    "getAddressKey",    "setAddressKey" },
        });

    private int id;
    private String name;
    private int addressKey;

    public int getId() { return id; }
    public String getName() { return name; }
    public int getAddressKey() { return addressKey; }

    public void setId(int val) { id = val; }
    public void setName(String val) { name = val; }
    public void setAddressKey(int val) { addressKey = val; }

    // to be continued
}


The function getAddessKey() only returns the foreign key of an address record but not the data itself. However, providing a transparent navigation function is very easy to implement as illustrated in the following extension of the Customer class:

class Customer extends MappedObject  {                    
    // as before

    Address getAddress() throws SQLException {
        return new Address(getAddressKey());
    }

}


Also 1:n relationships or cascade delete can be implemented very easily. Furthermore it turned out in daily practice that self-defined functions of this kind improve the common understanding of the application and the traceability of system behaviour in debugging sessions. When using a layered architecture with data access objects for database access encapsulation, the advantage of transparent relationship support becomes almost irrelevant. At last it doesn't count if the implementation of navigation functions is based on object networks or any other technique as long as it is simple. The following example shows two typical (a little simplified) functions from an enterprise solution to demonstrate that relationship support is not important for a convenient implementation:

class CustomerStore {

    // Proposed implementation of an address retrieval with an
    // O/R mapper with relationship support (1:1)
    Address getCustomerAddress(Customer customer) throws SQLException {

            return customer.getAddress();
    }

    // Proposed implementation of  a 1:n relationship navigation using an
    // O/R mapper with relationship support
    Collection getCustomerOrders(Customer customer) throws SQLException {
            return customer.getOrders();
    }

    // Implementation of an address retrieval with PriDE
    Address getCustomerAddress(Customer customer) throws SQLException {
            return new Address(customer.getAddressKey());
    }

    // Implementation of an order retrieval with PriDE
    Collection getCustomerOrders(Customer customer) throws SQLException {
            Order order = new Order(customer.getId());
            return order.query(new String[] { "customer_id" }).asArrayList()
;
    }

    // to be continued
}


The complete source code for the examples can be found in examples/relation.


Home Introduction Javadoc