super() type functionality on ORM CFC - orm

When I use CF9's ORM feature and generate an explict setter for my ORM CFC, is there anyway to call the default funcitionailty of the ORM CFC after i have done the work needed in the method. For example i am looking for something like this. Obviosuly the code will not run , and super is the wrong concept since the ORM CFC isnt inherting anything, but thats the type of functionality I am looking for.
public void setMovie(String movie){
if(movie == "inception"){
ORMCFC.super().setMovie("Greatest movie ever made")
}else{
ORMCFC.super().setMovie(movie)
}

In your model CFC for the ORM you can specify additional "decorator" functions.
component persistent="true" table="Movie" schema="dbo" output="false"
{
/* properties */
property name="MovieNo" column="MovieNo" type="numeric" ormtype="double" fieldtype="id" ;
property name="Name" column="Name" type="string" ormtype="string" ;
/* decorator */
public void function setMovie(name)
{
if(name == "inception"){
setName("Greatest movie ever made")
}else{
setName(name)
}
}
}
Otherwise if you need to (using your example) setMovie() you will need to do an EntityLoad or create a new entity to set a value to.

Related

unmapped class error with coldfusion 9.0.1 orm

i have to model classes User and Order. what i want is to have a relationship between them, so that a user has many orders, which in this case would be a one-to-many rel. which i defined in the User.cfc as follows:
property name="orders"
fieldtype="one-to-many"
cfc="Order"
fkcolumn="userID"
type="array";
each of this cfcs can be loaded through EntityLoad( Entity Name ) without any problems; i see all the data in the dump output.
however, as soon as i put the orders relationship in the User.cfc, it all breaks apart and i get an error message:
Association references unmapped class: Order
here's the code for the cfcs
User.cfc
component persistent="true" datasource="otherDatasource"
{
property name="id" fieldtype="id";
property name="userName";
property name="password";
property name="firstName";
property name="lastName";
property name="title";
property name="orders"
fieldtype="one-to-many"
cfc="Order"
fkcolumn="userID"
type="array";
function init()
{
return this;
}
}
Order.cfc
component persistent="true"
{
property name="id" fieldtype="id" generator="guid";
property name="quantity";
property name="period";
property name="region";
property name="createdAt" ormtype="date";
function init()
{
return this;
}
}
Any ideas what i'm doing wrong here?
it seems as i have my answer. coldfusion 9.0.1 orm isn't capable of building a relationship between tables in different databases.

Dynamic property defaults in CF9 ORM

How do you set up dynamic property defaults on CF9 ORM objects?
For instance, I know I can set a property default like this:
property name="isActive" default="1";
But what if you want to have a dynamically generated default, such as a date or a UUID?
property name="uuid" default="#createUUID()#";
...throws an error - so what's the workaround for this?
When an Entity object is created the objects constructor is called. This is a great place for running "setup" code.
User.cfc
component persistent="true"
{
property name="id" fieldtype="id" generator="native";
property name="secretKey";
public User function init() {
if (isNull(variables.secretKey))
setSecretKey(createdUUID());
return this;
}
}
Have you tried overloading the getter?
public string function getUUID() {if(variables.UUID EQ ""){ return createUUID(); } else { return variables.firstName; }; }
I can't test that from where I'm at, but I would try.

NHibernate Custom Collections hack works outside of a transaction, but not inside

Following the technique described here, I was able to populate a domain object that uses custom collections for its children. The relevant property mapping looks like this:
<component name="Contacts" class="My.CustomList`1[[Domain.Object, DomainAssembly]], MyAssembly">
<set name="InnerList">
<key column="PARENT_ID" />
<one-to-many class="Contact" />
</set>
</component>
My custom collection class exposes the InnerList property as an ICollection like so:
protected System.Collections.ICollection InnerList
{
get
{
return this;
}
set
{
Clear();
foreach (DomainObject o in value)
{
Add(o);
}
}
}
This worked like a charm to load data from the database and not have to abandon my rather useful custom collection class.
Then I moved on to try implement saving, and following the advice given in this thread, decided to wrap every call to NHibernate in a transaction.
Now when I commit following my load, NHibernate throws an InvalidCastException: "Unable to cast object of type 'My.CustomList`1[Domain.Object, DomainAssembly]' to type 'Iesi.Collections.ISet'."
Is there a way to make this work the way I expect it to?
EDIT:
Following the lead provided by Raphael, I tried switching to ICollection<T> which gives me a different InvalidCastException when I commit the transaction: Unable to cast object of type 'My.CustomList`1[Domain.Object]' to type 'NHibernate.Collection.IPersistentCollection'.
Change the property to be of type
IList<T>

NHibernate: how to map a Point?

I have a class which contains a collection of Points (PointF's rather).
I want to be able to persist instances of that class using NHibernate.
My class looks somewhat like this (simplified):
public class MyClass
{
public IDictionary<string, PointF> Points = new Dictionary<string, PointF>();
public void AddPoint( location, PointF position )
{
Points.Add(location, position);
}
}
The mapping of this collection looks like this (simplified):
<map name="Points" table="Locations">
<key column="MyClassId" />
<index column="LocationName" />
<composite-element class="System.Drawing.PointF, System.Drawing">
<property name="X" column="X" />
<property name="Y" column="Y" />
</composite-element>
</map>
The problem now is, that NHibernate throws an error while processing the mapping file, since PointF is not a known (mapped) entity.
How can I solve this in the most simple way ?
How can I make sure that NHibernate is able to persist my collection of locations (with their coordinates (point) ?
The problem is not that you didn't map the type PointF - because you map it as composite-element, which is correct.
When mapping such types you need to make sure
that properties are writable (which is luckily the case here)
that it has a default constructor, which is not the case here.
So how should NH create new instances when there is not default constructor? It can't.
Your options are:
implement an interceptor or NH event. I think it is possible to inject code there which creates instances of certain types, but I don't know how.
implement a NH user type (derived from ICompositeUserType), which is not too hard to do
map another type (eg. a wrapper to PointF)

how to do constructor injection when mapping a class as component in nhibernate?

For mapping component in nhibernate , is there a way in the hmb file we can indicate a overlaoded constructor to be used instead of default one.
In below mapping nHibernate will use the default constructor of MyClass when reading data from database - I am wondering if we can instruct nhibernate to use a overloaded constructor instead ?
<component name="MyProperty" class="MyClass" >
<property name="Member1" column="member_1" />
<property name="Member2" column="member_2" />
<property name="Member3" column="member_3" />
</component >
Edit #1
Alternatively , does nHibernate allow to map a static value to a property instead of a column ?
Something like below:
<component name="MyProperty" class="MyClass" >
<property name="Member1" column="member_1" />
<property name="Member2" column="member_2" />
<property name="Member3" **value="555"** />
</component >
NHibernate will always use the default constructor to instantiate an object of the type, (unless you want to create some kind of DTO and retrieve it via HQL) and then it will use the properties (or backing fields if specified) to populate the object.
If you have a type for which you do not want to expose a default (no-args) constructor, but you want to make sure that you can only instantiate the type via a specific constructor, then I always do it like this:
public class MyClass
{
private MyClass()
{
// Default constructor has been made private, so it is not usable
// by user code, but NHibernate requires a default constructor
// (it may be private)
}
public MyClass( int member1, int member2, string member3 )
{
}
}
The only standard way you can use constructor with parameters in NHibernate using select new HQL construct:
select new Family(mother, mate, offspr)
from Eg.DomesticCat as mother
join mother.Mate as mate
left join mother.Kittens as offspr
Otherwise it uses parameterless constructors for all purposes. I'm not sure whether this can be altered by hacking NHibernate internals (IClassPersister, IInterceptor, etc.)