blob: 5fec1ddbc335a4f7febf6f3bc87600f38124ea74 [file] [log] [blame]
Title: Generic Persistent Class
<P><A href="http://cwiki.apache.org/CAY/generic-dataobjects-example.html" class="external-link" rel="nofollow">Download the example code</A></P>
<H2><A name="GenericPersistentClass-WhatIs%22GenericPersistentClass%22"></A>What Is &quot;Generic Persistent Class&quot;</H2>
<P>Each kind of persistent objects (such as &quot;Artist&quot; or &quot;Painting&quot;) is described in Cayenne by a single ObjEntity. The most common and useful scenario is mapping an ObjEntity to a &quot;specialized&quot; Java class, one class per entity. But there is an alternative - use a single generic persistent object class to map any entity.</P>
<DIV class="panelMacro"><TABLE class="tipMacro"><COLGROUP><COL width="24"><COL></COLGROUP><TR><TD valign="top"><IMG src="http://cayenne.apache.org/docs/1.2/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></TD><TD><B>Generic DataObject hints</B><BR><UL>
<LI>Accessing generic objects is done via DataObject API (see examples below).</LI>
<LI>The simplest &quot;generic&quot; object class for all practical purposes is <TT>CayenneDataObject</TT>.</LI>
<LI>&quot;Concrete&quot; DataObject classes are by definition &quot;generic&quot; as they implement <TT>DataObject</TT>.</LI>
</UL>
</TD></TR></TABLE></DIV>
<DIV class="panelMacro"><TABLE class="tipMacro"><COLGROUP><COL width="24"><COL></COLGROUP><TR><TD valign="top"><IMG src="http://cayenne.apache.org/docs/1.2/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></TD><TD><B>When to Use Generic Objects</B><BR>Generic objects are not type-safe and are not convenient for manual coding. Most applications should stick to concrete classes. Generic objects are useful in cases when all persistent properties are not fully known at compile time. It is also possible to use a hybrid approach when new persistent properties are added to the existing concrete class at runtime.</TD></TR></TABLE></DIV>
<H2><A name="GenericPersistentClass-MappinginCayenneModeler"></A>Mapping in CayenneModeler</H2>
<P>If you don't enter anything for Java Class of an ObjEntity, Cayenne assumes generic mapping and uses the following implicit rules to determine a class of a generic object. First it will check whether a DataMap &quot;Custom Superclass&quot; is set. If so, runtime uses this class to instantiate new objects. If not, <TT>org.apache.cayenne.CayenneDataObject</TT> is used.</P>
<P><SPAN class="image-wrap" style=""><IMG src="generic-persistent-class.data/custom-generic-object.jpg" style="border: 0px solid black"></SPAN></P>
<P>CayenneModeler and Ant class generators skip ObjEntities that are mapped to CayenneDataObject explicitly or have no class mapping (i.e. implicitly mapped to a generic class).</P>
<H2><A name="GenericPersistentClass-HowtoUseGenericDataObjects"></A>How to Use Generic DataObjects</H2>
<H4><A name="GenericPersistentClass-UseStringentitynameinplaceswhereyouwouldpreviouslyuseJavaclassasamethodargumenttogetaholdofaDataObject."></A>Use String <EM>entity name</EM> in places where you would previously use Java class as a method argument to get a hold of a DataObject.</H4>
<P>Create a new object:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">
DataObject author = context.newObject(<SPAN class="code-quote">&quot;Person&quot;</SPAN>);
</PRE>
</DIV></DIV>
<P>Build SelectQuery:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">
Expression e = ExpressionFactory.likeIgnoreCaseExp(<SPAN class="code-quote">&quot;subject&quot;</SPAN>, <SPAN class="code-quote">&quot;%first%&quot;</SPAN>);
SelectQuery q = <SPAN class="code-keyword">new</SPAN> SelectQuery(<SPAN class="code-quote">&quot;Message&quot;</SPAN>, e);
</PRE>
</DIV></DIV>
<H4><A name="GenericPersistentClass-UseDataObjectAPItoread%2Fwritethevaluesinsteadorgetters%2Fsetters."></A>Use DataObject API to read/write the values instead or getters/setters.</H4>
<P>Determine object entity name:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">
DataObject object = ...;
<SPAN class="code-object">String</SPAN> entityName = object.getObjectId().getEntityName();
</PRE>
</DIV></DIV>
<P>Read a simple property value (attribute or relationship):</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">
<SPAN class="code-object">String</SPAN> subject = (<SPAN class="code-object">String</SPAN>) object.readProperty(<SPAN class="code-quote">&quot;subject&quot;</SPAN>);
</PRE>
</DIV></DIV>
<P>Read a &quot;nested&quot; property value spanning a chain of DataObjects:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">
<SPAN class="code-object">String</SPAN> name = (<SPAN class="code-object">String</SPAN>) object.readNestedProperty(<SPAN class="code-quote">&quot;author.lastName&quot;</SPAN>);
</PRE>
</DIV></DIV>
<P>Modify a property value:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java">
object.writeProperty(<SPAN class="code-quote">&quot;subject&quot;</SPAN>, <SPAN class="code-quote">&quot;Post On Topic&quot;</SPAN>);
</PRE>
</DIV></DIV>