MuraCon Notes - Schema, Schmema: Git'er Done with Mura ORM

October 02, 2013

Schema, Schmema: Git'er Done with Mura ORM - Matt Levine

This was one of my favorite talks at the conference. While I've only come up with 1 or 2 places where I would need Mura ORM in my apps, I very much like (what we already knew) that Blue River says they use their own product for everything -- ALL the sites they create are built with Mura. Blue River "eats their own dog food". While I know some of the Adobe properties are written in CF, I think it would go a long way to making Adobe CF a better product, if ALL of the Adobe web properties were built using ColdFusion /soapbox

Mura ORM - new feature in 6.1

was a feature for the Mura team to start
will eventually take over the base objects in Mura

a very lean Mura-specific approach to doing some ORM things but not meant to totally replace all other ORM stuff

BlueRiver is our own main client - they use Mura on everything
they eat their own dogwood
(Hey Adobe, are you listening?! Why aren't ALL the Adobe web properties written in ColdFusion?!)

Why Mura ORM?
started w/ a client need for approval chains
a structured chain of groups that a content version needed to flow thru
needed to create 5 new entities and didn't want to write a custom DAO for each one
started w/ 3 options
1 custom DAOs
-- too much work
-- no code re-use

2. Mura Class Extension Manager
great for targeting custom business logic in Mura
can extend a content Bean, etc
great for rendering events
or data events (persisting data)
adding custom values to be used within rendering and data events
think of Class Extension Manager as an Excel spreadsheet -- you're just adding columns to what's already there
but the minute you need, say, a 1 to many relationship....this isn't the tool to use any more
so, not good for "maintaing relationships"
not great for custom business logic
there's not a "component" that can mange this stuff easily
not great for directly querying the database either

only handles very simple entities
great for hooking attributes to existing Mura pages, but bad for complicated logic
if want the data to be stored in flat tables, then this is not the appropriate choice

3. CF based Hibernate ORM
(Slatwall uses the CF ORM and that bas 150 entities)
great for
easily defining properties
great for CRUD operations
managing relationship to other CF ORM entities
just describe the entity w/ properties and start using it!

not good for creating relationships to Mura core entities
(would we have to redo ALL the entities in Mura to make them ORM'd? This quickly went down a rabbit hole.
not great for working w/ DI/1
didn't want to deal w/ sharing hibernate sessions w/ other apps

in existing implementation of CF ORM -- it's a single-session...creates all kinds of crazy conditions
flags the data TO be saved UNTIL you save it
potential for plugins and sites having race conditions got really bad and complicated quickly
sharing an ORM session w/ other apps was really complicated to do CORRECTLY without causing issues

CF ORM errors are low level java errors. hard to debug issues

didn't need EVERYTHING Hibernate does anyway

So what if...
i roll my own ORM that works exactly how Mura works?

i could make them accessible via $.getBean( entity name)
and appplication.servicefactory( entity name )

takes advantage of DI/1

entity can have the same interactions - loadBy(), getFeed(), validate(), getIterator(), getQuery() addParam(), etc

this way, as Mura evolves, everything is consistent, and the orm entity code evolves too
filtering content works the same way too, etc

want to be targetable by Mura events
onBeforeMyEntitySave($)
etc

similar implementation / usage to CF ORM

with some new attributes too
bundleable - auto bundles itself!
cacheName - which cache do you want to use (by default uses the Mura data cache)
dbtype - (fi not set, assumes the same dbtype as the Mura database)
manageSchema - can update the database from here, create new things in the schema, etc. set true/false to determine if this entity can edit the schema
useTrash - can this be retrieved from trash? (by default it's false....no point in retrieving transient objects from the trash)

could use same property attributes as orm
name, persistent, field type, cfc, fkcolumn, length, orderby, length, ormtype, etc
...with some new ones
nullable
required
validate
message
....note that they're the same as the ones on a Mura Form. these work the exact same way
(in fact, in 6.1 Mura forms now do serve-side validation!)

and a bunch of attributes for validation
examples:
minValue, maxValue, inList, method, lt, lte, eq, minCollection, etc
has to be at LEAST for items long
can't be the word "blue"
whatever little validations you want
the catch: the "message" attribute needs to describe WHY it failed

...so that's what we built...

simple entity:
component extends=mura.bean.beanORM" entityName="widget" table="widgets"
{
property name=widgetid" fieldtype="id"
}

...instead of persistent=true ala cf orm, you just extend that mura.bean.beanoRM object

widget = $.getBean('widget");

$ = application.serviceFactory.getBean( ... );
widget.setName("MyWidget").save().getErrors();

...and that's all you'd have to do to get it to work

widget has many options
one-to-many relationship
can do
widget.getOptionsIterator().getQuery() to see all of the contents in that relationship, etc.

mura.bean.beanORMversioned
how versioned entities
works the same way
all the entities know the version of the content/object of which they're associated so things like .next() always works correctly, etc.

the writeDump (get query()) thing will show the ACTUAL SQL BEING WRITTEN in the debug output! outstanding!

kind of in beta right now, but will be in 6.1 core