CF9 ORM relationships – hasProperty oddity
In my CF9 ORM application, I have a magazine object. Each magazine has a single genre (e.g. Craft, Sports, etc.) – so I have a many-to-one relationship set up on the magazine.cfc:
component output="false" persistent="true"
{
// identifier
property name="magazineid" fieldtype="id" setter="false" generator="identity";
// properties
property name="title";
property name="genre" cfc="genre" fieldtype="many-to-one" fkcolumn="frn_genreid";
}
The genre.cfc looks like this:
component output="false" persistent="true"
{
// identifier
property name="genreid" fieldtype="id" setter="false" generator="identity";
// properties
property name="genre";
property name="magazines" cfc="magazine" fieldtype="one-to-many" fkcolumn="frn_genreid";
}
It all works nicely, until I want to try removing the genre from the magazine.
If I create a new magazine entity, the genre property contains an empty string (confirmed by dumping the object). And the hasGenre() method returns false.
If I load an existing magazine entity, the genre property contains a genre object, and hasGenre() returns true.
So to try to remove the genre, I use:
magazine.setGenre( '' );
to set the genre property to an empty string, just like in the new entity – but hasGenre() still returns true – why?
If I instead use:
magazine.setGenre( {} );
to set the genre property to an empty struct, hasGenre() now returns false, and everything works OK.
But what is the difference between the empty string that I set manually, and the empty string that’s present when a new entity is created? And why do they return different results for hasGenre()?
Comments
- Sam Farmer
-
Did you try using the removeGenre() method?
- 18 August 2010, 14:01
- Reply
- Seb Duggan
-
Because the magazine entity has only one genre, it doesn't have the addGenre() and removeGenre() methods - they are only there for one-to-many and many-to-many relationships...
- 18 August 2010, 14:30
- Reply
- Brian Kotek
-
First, you really should be setting one side as the owning side in bidirectional relationships. More at http://www.barneyb.com/barneyblog/2010/04/09/dont-forget-inverse-true/ and http://www.briankotek.com/blog/index.cfm/2009/12/21/More-on-CF9-ORM-Relationships
Second, the CFDUMP is lying to you. Well, not really lying, but what you see as an empty string is actually a null value. And that's why the two are different. When you set the genre to an empty string, the hasGenre returns true because the genre is not null.
First, I'd highly recommend using a relationship management method to enforce the integrity of your bidirectional relationship. You can find out more at the above links, as well as: http://www.barneyb.com/barneyblog/2010/04/14/domain-model-integrity/
Second, if you actually want to set the value to null, you need to use JavaCast:
setGenre( JavaCast( 'null', 0 ) );
Hope that helps.
- 18 August 2010, 16:30
- Reply
- Seb Duggan
-
Thanks Brian - some very useful stuff in there!
I'm only just starting with ORM, so I've still got a lot to learn; but I'm putting together a collection of some very useful blog posts...
- 18 August 2010, 20:03
- Reply