Advanced Customization > Services and Infrastructure Customization > System Generation > Modeling Business Objects > Modeling Columns
  
Modeling Columns
Modeling Columns
GenAsPersistable and GenAsBinaryLink provide three mechanisms for specifying database columns:
1. properties (an array of GeneratedPropertys) represent strings, numbers, booleans, etc.
2. foreignKeys (an array of GeneratedForeignKeys) reference other persistent objects (and are stored as a classname/key pair)
3. roleA/roleB (GenAsBinaryLink only) are a special form of a foreign key used in associations
Additionally derivedProperties (an array of DerivedPropertys) provide convenience accessors to properties and foreign keys.
It is sometimes useful to collect a set of properties together into its own class which can then be managed as an entity and aggregated into a persistent object. The GenAsObjectMappable annotation exists for this purpose and is widely utilized by Windchill “cookies”. When a GenAsObjectMappable-annotated class is specified as the type for a GeneratedProperty, all its properties become columns in the owning class’s table. To prevent name-collisions, the names are “mangled” using a character/number pattern dictated by an arcane algorithm; it is this mangling that accounts for the “idA3” in idA3containerReference and the mapping of Persistable.thePersistInfo.theObjectIdentifier.id to idA2A2.
GeneratedProperty
An example of GeneratedProperty in our SimpleExample (name, which is required and of type String) has already been shown. GeneratedProperty supports a number of annotation members for controlling generation and behavior. See the Windchill JavaDoc for more information.
GeneratedForeignKey
A foreign key was not modeled, it was inherited from WTContained.
Listing 9: container definition snippet
01 @GeneratedForeignKey(name="ContainerLink",
02 foreignKeyRole=@ForeignKeyRole(name="container", type=wt.inf.container.WTContainer.class, referenceType=wt.inf. container.WTContainerRef.class, supportedAPI=SupportedAPI.PRIVATE,
03 constraints=@PropertyConstraints(required=true)),
04 myRole=@MyRole(name="contents", supportedAPI=SupportedAPI.PRIVATE))
The impact of the container reference had on SimpleExample’s schema is that it resulted in two columns (previously discussed). In fact, if we peel this back further, we can see that we got these fields from WTContainerRef – a GenAsObjectMappable – by way of ObjectReference. We can say that a foreign key is “simply” another property (and, in fact, you could model a property with a type of ObjectReference as the type and accomplish the “same” results (from the perspective of the columns that would be created)), however the Windchill persistence layer recognizes foreign keys as a type of association and can manage them for you. In particular:
you can prevent the foreignKeyRole object from being deleted (when it participates in your assocation) by setting owner=false
you can cause the myRole object to be deleted when the foreignKeyRole object is deleted by setting cascade=true
when cascade=false (the default value) and foreignKeyRole role is deleted, the reference held by myRole will automatically be cleared
you get accessors for both the reference and the referenced object generated for you
you can automatically retrieve the referenced object (when required=true) by setting autoNavigate=true, preventing an additional database hit when accessing the referenced object
you can navigate the foreign key link just as you would any other binary link.
The GeneratedForeignKey is used when a given persistable is associated to at most one other persistent object. It is preferable to utilize GeneratedForeignKey over a GeneratedProperty of some concrete subtype of WTReference because the former makes it possible for the Windchill persistence architecture to manage the reference as an association. However, there are exceptions to this. In particular, associations to WTPrincipals (users) should be modeled as GeneratedPropertys of type WTPrincipalReference rather than as GeneratedForeignKeys. This is because we don’t need the association management (users can’t be deleted) and because we only want accessors for the reference (which contains everything anyone should ever need to know about users).
* 
Just as with GeneratedRoles, you can constrain an existing foreign key (modeled on a parent class/interface), as is commonly done to constrain an iteration’s master. When constraining a foreign key, you need only provide the values that are different from that of the foreign key you’re inheriting from; you needn’t faithfully re-specify all of the properties of your parent.
GeneratedRole
The GeneratedRole annotation is used to describe the role A and B of a GenAsBinaryLink, which we saw earlier in SimpleExampleLink. Roles can be thought of as special foreign keys associating the link with two persistables (and have the same inheritance capabilities as foreign keys). Whereas foreign keys are applicable only when the cardinality of the associated role is 0-1 and where the association requires no additional data (properties), binary links are applicable when the association is many-to-many, when the association carries properties, or when the association would otherwise be persisted on a PTC business object (since you cannot alter existing PTC classes).
DerivedProperties
Derived properties aren’t themselves persisted, but they do provide convenience accessors (getters, setters, and query constants) to persisted properties that would otherwise be buried in cookies or across foreign key references. Let’s say you have a field c which is buried inside a cookie b which is itself buried inside a cookie a which is a property of our current class.
We could access it using this.getA().getB().getC(), being careful to handle possible NullPointerExceptions should the cookies not be initialized. Better yet, we could just add this derived property to our class and let everything (including the handling of NullPointerException) be handled for us.
Listing 10: a.b.c derived property
@DerivedProperty(name="c", derivedFrom="a.b.c")
With this derived property, we can now simply call this.getC().
If you need to cross a foreign key to access a field in the associated object, use the “>” delimiter after the foreign key’s name in place of “.”. To directly access the name of the associated master, WTPart relies on the following derived property:
Listing 11: master>name derived property
@DerivedProperty (name="name " , derivedFrom="master>name " )