I have two objects, Person and Family. I use a join table called "join_person_family" to track this many-to-many relationship. The join table has another property called "IS_PRIMARY" that I want to get at and filter when instantiating the person objects with EntityLoadByExample(), but I don't know how to do this with CF ORM. I could do this easily through SQL, but I'm trying to use ORM as much as possible. There may also be another way to track this property, but I can't think of anything. Thanks in advance for any help.
Here is the Family.cfc:
<cfcomponent hint="I am a Family" output="false" persistent="true" extends="_Proxy">
<cfproperty name="FAMILY_ID" hint="FAMILY_ID" type="numeric" ormtype="int" length="11" fieldtype="id" generator="identity" required="true"/>
<cfproperty name="PERSON" hint="PERSON" fieldtype="many-to-many" cfc="person" linktable="join_family_person" FKColumn="FAMILY_ID" inversejoincolumn="PERSON_ID" lazy="true"/>
<cfproperty name="STATUS" type="string" ormtype="string" length="45"/>
<cfproperty name="COMMENT" hint="COMMENT" type="string" length="255"/>
<cffunction name="init" hint="constructor" access="public" returntype="family" output="false">
<cfscript>
return this;
</cfscript>
</cffunction>
</cfcomponent>
Here is the Person.cfc:
<cfcomponent hint="I am a Person" output="false" persistent="true" extends="_Proxy">
<cfproperty name="FAMILY" hint="FAMILY" fieldtype="many-to-many" cfc="family" linktable="join_family_person" FKColumn="PERSON_ID" inversejoincolumn="FAMILY_ID" lazy="true"/>
<cfproperty name="PERSON_ID" hint="PERSON_ID" type="numeric" ormtype="int" length="11" fieldtype="id" generator="identity" required="true"/>
<cfproperty name="USER" hint="USER" fieldtype="one-to-one" cfc="mend_user" FKColumn="USER_ID" lazy="true"/>
<cfproperty name="FIRST_NAME" hint="FIRST_NAME" type="string" length="45"/>
<cfproperty name="LAST_NAME" hint="LAST_NAME" type="string" length="45"/>
<cfproperty name="STATUS" hint="STATUS" type="numeric" ormtype="int"/>
<cffunction name="init" hint="constructor" access="public" returntype="person" output="false">
<cfscript>
return this;
</cfscript>
</cffunction>
Found this response, https://groups.google.com/forum/?hl=en&fromgroups=#!topic/cf-orm-dev/6Fox77MAcbs. After reading that I think that approach is actually superior anyway.
A intermediate entity with many-to-one relationships with the joining objects would allow me to use EntityLoadByExample() to get the relevant person objects filtered by "IS_PRIMARY". Then I could filter the person objects if need be.
Related
Mapping Two cfc objects via ORM, on execution a Dump shows the data for only one parent cfc object for table=products while the array of cfc table=department is coming back as (empty string) in output .
<cfcomponent persistent="true" table="products" >
<cfproperty name="productID" column="id" fieldtype="id" type="numeric" generator="increment">
<cfproperty name="name">
<cfproperty name="price">
<cfproperty name="description">
<cfproperty name="imageurl">
<cfproperty name="departmt" fieldtype="many-to-one" cfc="departmt" fkcolumn="dept_id" lazy="true">
<cfcomponent persistent="true" table="department">
<cfproperty name="id" column="dept_id" fieldtype="id" type="numeric" generator="increment">
<cfproperty name="name" column="dept_name">
<cfproperty name="location" >
</cfcomponent>
I work primarily in ColdFusion, a non-compiled language, but this is a general question for all languages.
I'm creating objects with getters/setters as well as CRUD methods. Here's a sample:
<cffunction name="getPeriodStartDate" output="false" returntype="Numeric">
<cfreturn VARIABLES.PeriodStartDate />
</cffunction>
<cffunction name="setPeriodStartDate" output="false" returntype="Void">
<cfargument name="PeriodStartDate" type="Numeric" required="true" />
<cfset VARIABLES.PeriodStartDate = ARGUMENTS.PeriodStartDate />
</cffunction>
<cffunction name="getDollarAmount" output="false" returntype="Numeric">
<cfreturn VARIABLES.DollarAmount />
</cffunction>
<cffunction name="setDollarAmount" output="false" returntype="Void">
<cfargument name="DollarAmount" type="Numeric" required="true" />
<cfset VARIABLES.DollarAmount = ARGUMENTS.DollarAmount />
</cffunction>
<cffunction name="read" output="false" returntype="Query">
<!---
READ QUERY
--->
<cfreturn _qData />
</cffunction>
<cffunction name="create" output="false" returntype="Void">
<!---
INSERT QUERY
--->
</cffunction>
<cffunction name="update" output="false" returntype="Void">
<!---
UPDATE QUERY
--->
</cffunction>
<cffunction name="delete" output="false" returntype="Void">
<!---
DELETE QUERY
--->
</cffunction>
Obviously the get methods and the read() methods will return a value.
But, is there any benefit to have the other methods return a value - perhaps a Boolean?
I've worked in Flex/ActionScript and remember that in most cases, I needed to return some value from a method and set a variable to that result in order to prevent the next line of code from processing:
function myFunc() {
x = getSomething();
y = getSomethingElse(x);
}
If you return this on your setters, you can chain the setters. I think CF10 accessors return thisto enable chaining by default.
I read that returning void would be more efficient a while back, but I'm not sure if it is true anymore. I doubt the difference would be noticeable.
I have this mapping
<class name="Person" table="person">
<id name="Id" column="id" type="Int32" unsaved-value="0">
<generator class="native" />
</id>
<property name="Code" column="code" type="String" not-null="true" />
<property name="FirstName" column="firstName" type="String" not-null="true" />
<property name="MiddleName" column="middleName" type="String" not-null="false" />
<property name="LastName" column="lastName" type="String" not-null="false" />
<join table="personPhoto" optional="true">
<key column="personId" />
<property name="Photo" column="pictureContent" not-null="false" />
</join>
and the generated SQL always use left outer join, which is correct.
However, is it possible to tell HQL to query only from person table, since I'm not always need 'Photo' property? And how?
Is there a one-to-one relationship between person and personPhoto columns?
If you want to load the person's photo lazily, I believe you have to change join mapping to one-to-one mapping and create a new class for personPhoto. This way Hibernate would be able to insert a proxy object.
I have two almost identical Beans.
Bean "Item" contains a unique identifier (primary key), a name and an array that contains structs with data for different Users that are related to the "Item".
Bean "User" contains a unique identifier (primary key), a firstname, a lastname and an array that contains structs with data of different Items that are related to the "User".
Both components contain two methods that write new data to the structs in the array or delete array elements and the setters and getters for the arguments.
The components deviate from each other only through theire argument names, the number of arguments each init method takes and the number of getters and setters.
So i want to create an "Abstract" Bean from which "Item" and "User" inherit. I can do so by using extends in the Beans to get the abstract methods, but how do i override the argument names and variable names. I.e. the argument name ArrayOfData in the AbstractBean does not really tell someone anything. I would like to have ItemHasMaterialsArray and UserHasItemsArray as names in the Item and User beans.
AbstractBean
<cfcomponent name="AbstractBean" output="false">
<cffunction name="init" access="public" hint="constructor" returntype="AbtractBean">
<cfargument name="Identifier" required="false" type="Numeric" default="0">
<cfargument name="Name" required="false" type="String" default="">
<cfargument name="ArrayOfData" required="false" type="Array" default="#arrayNew(1)#">
<cfset variables.instance = structNew() />
<cfset setIdentifier(arguments.identifier) />
<cfset setName(arguments.name) />
<cfset setArrayOfData(arguments.ArrayOfData) />
<cfreturn this />
</cffunction>
<cffunction name="updateArrayOfData" access="public" output="true" returntype="boolean">
<cfargument name="blank" type="Struct" required="true">
<cfset var i = 0 />
<cfset var form = arguments.blank />
<cfset var ArrayOfData = arrayNew(1) />
<cfset ArrayOfData = this.getArrayOfData() />
<cfloop index="i" from="#arrayLen(ArrayOfData)#" to="1" step="-1">
<cfif ArrayOfData[i].Amount neq structFind(form,ArrayOfData[i].Id) and LsIsNumeric(structFind(form,ArrayOfData[i].Id))>
<cfset ArrayOfData[i].Amount = structFind(form,ArrayOfData[i].Id) />
<cfelse>
<cfset arrayDeleteAt(ArrayOfData,i) />
</cfif>
</cfloop>
<cfset setArrayOfData(ArrayOfData) />
<cfreturn true />
</cffunction>
<cffunction name="deleteArrayOfDataElement" access="public" output="false" returntype="boolean">
<cfargument name="blank" type="Struct" required="true">
<cfset var i = 0 />
<cfset var form = arguments.blank />
<cfset var ArrayOfData = arrayNew(1) />
<cfset ArrayOfData = this.getArrayOfData() />
<cfloop index="i" from="#arrayLen(ArrayOfData)#" to="1" step="-1">
<cfif not listFind(form.del,ArrayOfData[i].UserId,',')>
<cfset arrayDeleteAt(ArrayOfData,i) />
</cfif>
</cfloop>
<cfset setArrayOfData(ArrayOfData) />
<cfreturn true />
</cffunction>
<cffunction name="setIdentifier" hint="setter" access="private" output="false" returntype="Void">
<cfargument name="identifier" required="true" type="Numeric" hint="Primary Key, really" />
<cfset variables.instance.Identifier = arguments.Identifier />
</cffunction>
<cffunction name="getIdentifier" hint="getter" access="public" output="false" returntype="Numeric">
<cfreturn variables.instance.identifier />
</cffunction>
<cffunction name="setName" access="private" output="false" returntype="Void">
<cfargument name="name" required="true" type="String" />
<cfset variables.instance.Name = arguments.Name />
</cffunction>
<cffunction name="getName" access="public" output="false" returntype="String">
<cfreturn variables.instance.Name />
</cffunction>
<cffunction name="setArrayOfData" access="private" output="false" returntype="Void">
<cfargument name="ArrayOfData" required="true" type="Array" />
<cfset variables.instance.ArrayOfData = arguments.ArrayOfData />
</cffunction>
<cffunction name="getArrayOfData" access="public" output="false" returntype="Array">
<cfreturn variables.instance.ArrayOfData />
</cffunction>
</cfcomponent>
In my User bean i would like the init method to also take firstname as an argument and override the variable names in my methods. With telling names my other code, i.e. calling the getters, would be much cleaner. User.getUserHasMaterials() reads much better than User.getArrayOfData(), imo. is this even possible? If not than i guess i will have to sacrifice variables readability to avoid duplication.
I think if you're trying to avoid duplication, it might make more sense to use composition rather than inheritance.
It looks like ArrayOfData could be be its own CFC, with methods like update(), delete(), and toArray(). Then you could pass an instance of ArrayOfData to either your User or Item object.
Your User CFC might look something like this:
<cfcomponent name="User">
<cffunction name="init" access="public" hint="constructor" returntype="User">
...
<cfargument
name="materials"
required="false"
type="ArrayOfData"
default="#arrayNew(1)#"
>
...
<cfset variables.materials = createObject("component", "ArrayOfData")>
<cfset setMaterials(arguments.materials)/>
<cfreturn this />
</cffunction>
<cffunction name="setMaterials">
<cfargument name="value" type="Array">
<cfset variables.materials.update(arguments.value)>
</cffunction>
<cffunction name="getMaterials">
<cfreturn variables.materials.toArray()>
</cffunction>
<cffunction name="deleteMaterials">
<cfargument name="blank">
<cfset variables.materials.delete(arguments.blank)>
</cffunction>
I'd like to write the following in script syntax rather than the old style tag syntax.
<cfcomponent persistent="true" table="AuditType" schema="Audit" >
<cfproperty name="AuditTypeID" column="AuditTypeID" ormtype="int" fieldtype="id" />
<cfproperty name="AuditTypeName" column="AuditTypeName" ormtype="string" />
<cfproperty name="AuditTypeSort" column="AuditTypeSort" ormtype="integer" />
</cfcomponent>
the cfscript syntax really is quite similar,
component persistent="true" table="AuditType" schema="Audit" {
property name="AuditTypeID" column="AuditTypeID" ormtype="int" fieldtype="id";
property name="AuditTypeName" column="AuditTypeName" ormtype="string";
property name="AuditTypeSort" column="AuditTypeSort" ormtype="integer";
}