An Object Relational Mapping (ORM) specification consists of mapping specifications for various object classes of an application needing persistence in a relational database. Following the KISS Principle #5 for ORM products, an ORM specification for Software Tree’s ORM products (JDX for Java, JDXA for Android, and NJDX for .NET) is defined declaratively in a text file. Keeping the ORM specification in a textual mapping file separate from the corresponding object class definitions (source files) is an important decoupling principle. This technique also avoids cluttering source files with mapping specification- related annotations or code. Here we discuss how to best order mapping specifications of different classes in a mapping file.
Our KISS Object Relational Mapping (ORM) products read a declarative ORM specification from a mapping file to initialize a mapping engine that performs various object persistence operations per the ORM specification. If needed, our products can make multiple passes over an ORM specification to deal with the mappings for various classes that may be specified in any order and could involve cross-references. However, to help in understanding, maintaining, and evolving an ORM specification more easily, here are some guidelines:
- Declare the mapping specification of an ELEMENT_CLASS (A) before declaring the mapping specification of a COLLECTION_CLASS (B) or a JOIN_COLLECTION_CLASS (C) involving that ELEMENT_CLASS (A)
- Declare the mapping specification of a JOIN_CLASS (P) before declaring the mapping specification of a JOIN_COLLECTION_CLASS (Q) involving that JOIN_CLASS (P)
- Declare the mapping specification of a referenced class (X) before declaring the mapping specification of a referencing class (Y) referencing that class (X) using the REFERENCES keyword in a RELATIONSHIP specification. The referenced class (X) may be a normal CLASS or a COLLECTION_CLASS or a JOIN_COLLECTION_CLASS. This may not always be possible if there are cross-referencing relationships but that is OK; our ORM products can handle that unavoidable ordering.
Essentially, try to declare something before using it. It is like we are making trees going from top to bottom, that is, from leaves to intermediate nodes to roots. In this analogy, a leaf is a standalone CLASS without any RELATIONSHIPs.
In other words, if we were to write the mapping specification on a long piece of paper and draw the following arrows, they should all preferably be pointing upwards:
- From a COLLECTION_CLASS to its ELEMENT_CLASS
- From a JOIN_COLLECTION_CLASS to its ELEMENT_CLASS or to its JOIN_CLASS
- From a referencing CLASS to its REFERENCEd classes
Also, for easier comprehension, it is good to keep the following arrangement:
- mapping of an element class above and close to the mapping of the corresponding collection class
- mapping of a join class above and close to the mapping of the corresponding join collection class
- mapping of a referenced classes above and close to the mapping of a class using those referenced classes.
Simply put, try to make those upward arrows as short as possible.
Here is a pseudo example of a harder to understand ORM specification.
Harder To Understand ORM Specification
And here is an example of the same ORM specification with an easier to understand ordering of the mapping specifications.
Easier To Understand ORM Specification
In summary, defining the mapping specification of a dependent class soon after defining the mapping specification(s) of the class(es) it depends on helps you more easily comprehend and evolve an ORM specification. This also optimizes the initialization process of an ORM engine as it may be able to avoid multiple passes of the ORM specification.
Learn more about the KISS ORMs, including how to get free trial versions, by visiting Software Tree’s website at https://www.softwaretree.com.