I'm very pleased to announce the Release Candidate of 0.6 of Transfer ORM for ColdFusion.
Since there has been such a huge leap forward in terms of functionality between 0.5 and 0.6, I decided to run a release candidate for a short while, before releasing a final build of 0.6.
Any and all commentary is welcome on this release, not only bugs, and feature requests , but suggestions on documentation, API, and anywhere else you feel the product could be improved.
(Yes, I know the documentation is quite possibly the ugliest thing you have ever seen ;) hopefully before the full release of 0.6 I can try and convince my graphic designer girlfriend to do some branding for me.... But have you tried to explain an Object Relational Mapper to a graphic designer?)
Transfer 0.6RC1 can be downloaded from here.
Now, on to the fun stuff: What is new in this release, well, pretty much everything I talked about recently and a bit more.
- Oracle Support.
Yes it is true! You can now use Transfer on Oracle!
- Lazy Loading.
Good for large, complex domains, compositional elements now have a 'lazy' attribute that can be set to true, e.g.
<onetomany name="Permission" lazy="true">
This means that the Permission objects won't be loaded until they are requested.
- Nullable properties on objects.
Now properties on objects can be set to a 'Null' value. A new 'nullable' property attribute adds two new methods: 'setPropertyNameNull()' and 'getPropertyNameIsNull()' which sets the value of the property to a configurable value that is designated to be NULL - be it an empty string, -123456789 or :::!!NULL!!:::
- Implemented the ability to 'decorate' TransferObjects, to provide greater customisation possibilities.
If you wish to write your own CFCs to be utilised by Transfer, you can. For example, if I had:
<object name="User" decorator="mysite.security.User">
When you run
getTransfer().get("User", 1);you will get an instance of 'mysite.Security.User' which wraps around the original transfer.com.TransferObject and automagically extends all the public methods of that object.
Very handy if you need a high level of customization to your objects.
- Now able to turn off internal transaction blocks within Transfer with an optional argument on create(), update(), save() and delete() calls.
Now you are able to make calls such as
getTransfer().save(user, false);and it will ignore the internal transactions - meaning you can wrap large commitments to the database in their own
<cftransaction>blocks, and not have to worry about conflicts with transactions inside of Transfer.
- Fixed the misspelling of 'objectDefinitions' in the XSD file. Note: This could cause 'object not found' errors if you are updating from a previous version of Transfer. Make sure you validate against the new schema.
It took up until 0.5 to find this spelling mistake! If you are using a previous version, make sure your configuration file is validated against the schema (a good idea anyway), to ensure you don't get confused by the change.
- Cached objects will now automatically synchronise data if a non-cached object is saved and/or deleted.
This was a shortcoming of the previous version, in that you could discard objects from the cache, and you could set them to time out, but if an object that wasn't in cache was committed to the database, and there was a cached object in scope - the changes wouldn't be reflected in the cache.
Now these changes are synchronised with the cached object, so that the data in cache is not out of sync with the database.
- clone() method on all generated objects. Clone will syncronise with cached objects on getTransfer().save(), getTransfer().update() and getTransfer().delete() calls.
You can now create a deep clone of any Transfer generated object, which is not stored in the Transfer cache.
However, as we looked at previously, any change made to the cloned version will be synchronised to the cache if it is committed to the database.
This means you can make changes to an object outside of the scope of the cache, if you need to.
- Put condition on 'onetomany' and 'manytone', allowing for composition filtered by a condition.
You are now also able to setup conditions on which objects are included when having a structure or array of composite objects.
For example, you may wish to -
<manytomany name="Permission" table="lnkPermission">
<condition property="isActive" value="1" />
This will filter only active permissions.
- find() function on manytomany and onetomany composition.
A new generated 'find' function, which will return back the index of the object you pass in if the collection is an array, or the key it is stored under, if it is a struct.
- insert-ignore, insert-refresh, update-ignore, update-refresh attributes on properties.
These new property attributes can tell Transfer not to insert or update these property values when committing to the database.
The refresh properties can tell Transfer to go back to the database after a update or insert and get the value of the property, and update the Transfer generated object.
This is particularly handy for setting objects with database default values, or populating objects with values created from database triggers.
- listByPropertyMap() and readByPropertyMap() to allow for using multiple property values to do reads and lists of objects.
These two new methods allow for listing and reading objects by a combination of property values, simply by passing in a struct of key-value pairs into the function.
For example -
properties = StructNew();
properties.firstName = 'Mark'
properties.lastName = 'Mandel'
user = getTransfer().readByPropertyMap("User", properties);
- Columns are aliased with property names on list*() operations.
By default, all list*() operations will apply the property name set in the configuration file as aliases to the columns that are returned from a list query.
A new optional 'useAliases' attribute that allows you to turn off column aliasing if you need to.
- Transfer.getTransferMetaData(className) so that you are able to get the Transfer meta data on an object.
This meta data was exposed for the Model-Glue:Unity integration, but could be used for a variety of purposes.
- discardByClassAndKey(className, key), discardByClassAndKeyArray(className, keyArray), discardByClassAndKeyQuery(className, keyQuery, keyColumn).
These methods allow you to discard objects from the cache, if they exist. This is useful for clustered environments and for batch deletions from the database.
- XML Schema now contains documentation, so you get help with your code hinting.
The XML schema contains all the help documentation, so in your XML editor you should get the documentation to display along with your code hinting.
- Update to Transferdoc
Incorporated the newest version of wwwObjectDoc into TransferDoc, which now gives us an ordered list of the methods on an object. (Thanks Aaron!)
- Bug fixes, refactoring and the like...
Also a big thanks to all those who contributed, helped out, gave me bugs, wrote blog posts, and anything else I can't think of right now, it is all very appreciated.
And if you haven't already, please join the mailing list .