mirror

mirror is the Object Relational Mapping used to handle the interactions between the java data model and the backend SQL database.

Transactions

The key feature of mirror that sets it apart from conventional ORMs and SQL databases is the use of long-term transactional viewpoints. Transactions are common in relational databases but they are normally very short-lived and cover the period of time when a block of data is written to the database. mirror takes an alternative approach where you lock specific records for updating or deleting (which may then automatically lock other records depending on the dependencies) and then you hold onto these locks until the human editor deems that the new data is correct.

While the lock is held, the transaction viewpoint is applied to the editors view of the data that they have locked. A second copy of all the locked records is created in java space and the data in these WritableRecords can deviate from the data held in the java PersistentRecord objects that represent the data in the database.

What this means is that an editor can make repeated edits to a set of records over a period of time and see these updates, but the general public only gets presented with the persistent data until the editor decides to commit the Transaction. If the editor decides to cancel their transaction then all of the assets associated with the WritableRecord are automatically discarded.

Triggers

mirror supports the definitions of triggers in java-space at multiple levels in the information hierarchy.

InstantiationTriggers
are triggers that get invoked either immediately before or immediately after a new record is created and made visible to the SQL database.
StateTriggers
are triggers that get invoked immediately before or after when a record on a given Table changes state between Persistent, Writable and Deleted.
FieldTriggers
are triggers that are registered on a given field on a Table and are invoked when this field changes value and can provide validity checks and / or data filtering.

If you describe the constraints on your system architecture in terms of these triggers then you get all the advantages of enforced data integrity while also maintaining the flexibility of the transactional viewpoints described above letting you build and extend complex systems while letting mirror do most of the heavy lifting for you.

Caching

mirror performs very aggressive caching of both records and the results of queries in java space. This means that as the load on a system goes up for a normal website usage distribution, the number of db queries per second actually reduces as the system migrates the most popular pages into memory.

It is therefore constructive to run mirror on a system which lets you allocate a sensible amount of memory to the JVM thereby letting the system automatically optimise the caches accordingly.