Introduction to Object Role Modeling

Copyright (c) 2007 Clifford Heath.

Example Models
Company
School Activities
Death
Address
Orienteering
Table of all examples

Congratulations, you're just a few minutes away from knowing a more agile way to design good database schemas. These models were created in ORM2 using NORMA. ORM2 terminology is emphasised on first use. Although the CQL here was generated from the ORM2, you can produce the same effect by writing it yourself.

CompanyDirectorEmployee

This model shows the some of the relationships of a person to a company of which they are a director or employee.

View the generated: CQL Ruby SQL

This model includes examples of the features of ORM2 you'll be seeing most often.


SchoolActivities

This model represents students representing their school in school-sanctioned activities.

The model has three interesting constraints:

Uniqueness over Student represents School in Activity:
Allows a given Student may only participate in a given Activity for a single School
Subset from Participation to Enrollment
Only for the School in which they're enrolled
Subset from Participation to Sanctions
Only if the School sanctions that activity.

The rules of elementarity require that every fact type having N roles has a uniqueness constraint over either N or N-1 roles, and never over fewer roles. This is satisfied here by the StudentParticipation having a uniqueness constraint over two of its three roles.

The subset constraints work like this. The student is enrolled in exactly one school, and the set of (School, Student) pairs is a superset of the (School, Student) pair inside the StudentParticipation ternary. In simple terms, this requires that each student who participates in some activity may only do so as a representative of the school in which they're enrolled, and not for any other school. The other subset constraint requires that such participation may only occur for an activity that is sanctioned by that school. The direction of the subset arrow is consistent with the arrows used in sub-typing, as shown in the next case.


Death

This example is more a curiosity than anything else, serving to illustrate a case that you might not otherwise think was possible. Person may play a unary role in the fact type "is dead". If they are in fact dead, we might wish to record some facts about the event of their death, so we nest (objectify) the "is dead" fact type as a new entity, Death. This allows us to associate their death with a value indicating the cause of death. The uniqueness constraint requires that we record only one cause of death.


Address

The Address model shows how a mass of fine semantic detail can be turned into an efficient relational database structure, through the miracle of absorption.

View the generated: CQL Ruby SQL

Note that the preferred identifier for Street covers all its functional roles. Essentially that means that whereever we have a Street, all the attributes of that street must be provided; so we can include them in more than one table without breaking the relational Third Normal Form, which would introduce unsafe duplication.

The same thing pertains for Address, so we can have an Address in both the Company and Person tables without breaking normalisation. Here's the generated SQL created by afgen:


Note also that the SQL doesn't enforce the uniqueness constraint requiring that each Address occurs once only. There's no need to. Each Address is identified by its roles, but more than one person may live at the same address, and a company might have its HQ there too. If you want all the distinct addresses, you can write an SQL UNION query for that.

If you want an Address table anyhow, you can mark it as independent, which is an instruction to the absorption process that an instance of this entity type might exist apart from any other roles it might play. Independent entity types are shown in ORM2 as having an exclamation point ! after their name. In order to represent an independent entity type in SQL, a separate table is always needed.

If you were to add a functional role to Address that's not part of its identifier, the rules of normalisation gazump absorption and Address will become an independent table. In that case, Company and Person would have each a large multi-part foreign key into the new Address table, so it might be preferable to introduce a surrogate key in the form of a database-allocated unique integer into the address entity, and mark that key as the preferred identifier instead. This can be done with minimal change to the semantic model, so any queries you have will probably still just work - this is a key advantage of the semantic approach.

Note that the absorption process must know all the entity types, fact types, and constraints for the model. If you add a single fact type or change a constraint, that might require that some concepts are represented in new tables, or different ones, and these changes can cascade, so that a small change in the conceptual model requires a large database migration. If you've written your program using the Constellation API, you'll have minimal rework.


Orienteering

Here's a three-part model of a system for the sport of Orienteering. The three parts cover administration, registration and scoring respectively, which also happens to map areas of interest to folk in different roles. Any feature may show on more than one diagram, and the ORM2 rules don't indicate that such an element has a special affinity with any diagram on which it appears. Concepts that appear in more than one place are shown with a drop-shadow. The diagrams are presented without much comment, and after that, the absorbed (compound) form is shown as an entity-relationship diagram.

Administration

A couple of new features are shown here. Number has a Value Constraint, which is similar to the role value constraints we saw before, except it applies to all Numbers.

Also here you'll see an external mandatory constraint without an exclusive cross. This one requires that an event is either part of a series, or has a name, or both. If and only if the event is part of a series, it must also have a number in that series - this is shown by the equality constraint, a circle with an = sign in it.


Registration


Scoring

View the generated: CQL Ruby SQL

This model also shows the resultant score for a given Entrant's Entry to a given Event. This value will be computed from the times of their visits to punches during the event, according to a scoring method as advised. The asterisks indicate that the role value is derived from other values in the model, or that some values may be derived and others now.