[Opensource] JoinedDataObject Documentation [LONG]

Michael Rimov rimovm at centercomp.com
Mon Jun 30 21:55:04 PDT 2003


Greetings all!

As promised in the checkin forums, I've made a first draft of documentation 
on the new JoinedDataObject from Expresso 5.1.  I'm including a copy and 
pasted version for everyone's perusal.  The full version, with UML 
diagrams, is checked into CVS].

Let me know if the doc doesn't work for you! :)
                                                 -Mike


JoinedDataObject [Since Expresso 5.1]




Introduction

As you might recall near the beginning of the chapter, Expresso is in the 
midst of abstracting services common to DBObjects into a series of 
interfaces that provide for generic access to multiple data source types. 
JoinedDataObject is an example of the results of this effort.

JoinedDataObject is very similar to MultiDBObject except that it was a 
ground up rewrite for efficiency, as well as its goal is to act to a client 
programmer just like a standard DataObject. While the convenience services 
available to DBObjects are often not available, the DataObject API is no 
less powerful. After all, DBMaint can accept any object that implements the 
DataObject interface for management. By extension, DBMaint can then manager 
a JoinedDataObject just like any other DBObject.



Creating a Joined DataObject




Defining your Join

This guide will not get into the details of database design when it comes 
to how to create a join on the SQL level. Rest assured, you will not have 
to figure out the SQL to create the join, you only need to know the theory 
of what is a join and when to use it.

So let's get into a concrete example of define your join. If you ever dig 
through the Download controller and its related DataObjects, you will 
notice that there is a relationship between the DownloadLog table and the 
DownloadFiles table. Specifically, the DownloadLog contains the File number 
of the specified table. But what if you want to view the DownloadLog AND 
the DownloadFile at the same time without multiple browser windows? This is 
where the JoinedDataObject comes into play.

Instead of creating a new subclass like you do for many other DataObjects, 
in a JoinedDataObject, you simply write a definition file, a special XML 
file, to define how the DataObjects are going to be joined together.

So let's show a JoinedDataObject that joins DownloadLog and DownloadFiles 
tables based upon the file number in Download Log.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dataobject-join PUBLIC "-//Jcorporate Ltd//DTD Expresso 
DataObject Join 5.1//EN" "http://www.jcorporate.com/dtds/jdbc-join_5_1.dtd">
<dataobject-join description="Download Log View">
         <dataobject className="com.jcorporate.expresso.ext.dbobj.DownloadLog"
             alias="DownloadLog"/>
         <dataobject 
className="com.jcorporate.expresso.ext.dbobj.DownloadFiles"
             alias="DownloadFiles"/>
         <relations>
                 <foreign-key local-alias-ref="DownloadLog" 
local-alias-key="FileNumber"
                     foreign-alias-ref="DownloadFiles" 
foreign-alias-key="FileNumber"/>
         </relations>
</dataobject-join>

Now let's split up the definition file bit-by-bit.
    * XML Definition and Doctype: True to any XML document, you need to 
give it the xml processing syntax and a Doctype. The doctype for 
JoinedDataObjects is database-join It is included within the Expresso code 
distribution for fast validation during runtime.
    * <dataobject-join/> This is the 'root' element of the join definition. 
It has one attribute called 'description', which is the equivalent of 
setDescription() for DBObjects. Whatever you put here, DBMaint will list as 
the description for the DataObject. It has no other functional bearing.
    * <dataobject/> For each table you wish to join with this database 
object, you need to list it here as dataobject elements. They have two 
elements. The class name of the DataObject , and an alias for the 
DataObject, who's purpose will be explained later.
    * <relations/> Following the listing of all DataObject , the relations 
section defines how the various DataObject are related. Usually there will 
be (X - 1) relations, where X is the number of DataObjects used in the Join.
    * <foreign-key/> Now it's time to define how the tables relate to each 
other. In it is the 'left' table, which is referred to as the local alias 
and key here, and the 'right' table, which, here is referred to as the 
'foreign' alias and key. As you can see from the example, the DownloadLog 
field named FileNumber corresponds to the DownloadFiles' field FileNumber.

When you have a complete file, you save it somewhere in your classpath, 
preferably somewhere that makes sense. An example we'll use is 
"/org/example/myapp/dbobj"

Now on to the purpose of an alias. As mentioned several times, 
JoinedDataObjects implement the DataObject API. One of the methods in the 
DataObject interface is: setFieldValue(String fieldName, Object o). We all 
know about the field names for various data objects, but how do we specify 
which dataobject to set the field of? MultiDBObject used the method 
setField(String shortName, String fieldName, String value); Obviously, we 
can't ue that and conform to the API. So JoinedDataObjects expect field 
names to be specially formatted. They go by the format [alias].[fieldName] 
. So, for example, to refer to the file number in DownloadLog, you would 
type in code:
setField("DownloadLog.FileNumber",4");

Although JoinedDataObject parses the string, to all external clients, it 
looks like a single data object, with weird field names.



Instantiating and Using a Joined DataObject




Manual Construction

JoinedDataObjects implement Defineable interface. That means that when you 
instantiate an Defineable object, you need to call the method 
setDefinition() before you can use the object. Defineable allows Expresso 
to uniquely differentiate objects by setting some sort of String value for 
the object to configure itself with. For AutoDBObject, for example, you set 
the table name to attach to. JoinedDataObjects take the path (in classpath) 
to the definition file. So let's use a sample:
import com.jcorporate.expresso.core.dataobjects.jdbc.JoinedDataObject;
import com.jcorporate.expresso.core.dataobjects.Securable;
//...

JoinedDataObject myjoin = new JoinedDataObject();
myjoin.setRequestingUid(Securable.SYSTEM_ACCOUNT);
myjoin.setDataContext("default");
myjoin.setDefinition("/org/example/myapp/dbobj/myjoin.xml");



Factory Method Construction

Expresso 5.1 now has a DataObject factory that considers all the 
construction order of various dataobjects including Securable and 
Definable. Instead of the sample above, you can instead write the code:
import com.jcorporate.expresso.core.dataobjects.DataObjectFactory;
import com.jcorporate.expresso.core.dataobjects.jdbc.JoinedDataObject;
import com.jcorporate.expresso.core.dataobjects.Securable;

//...
JoinedDataObject myjoin = (JoinedDataObject)DataObjectFactory
  .createObject(JoinedDataObject.class,
         "default", "/org/example/myapp/dbobj/myjoin.xml",
         Securable.SYSTEM_ACCOUNT);

Sometimes, the single factory method is more convenience than all the 
methods in the first example.


Typical Usage

Since JoinedDataObject implements DataObject API, the much of the same 
logic for DBObjects can also be applied to JoinedDataObjects. Examples:

    * Getting a field string value:
    *

    * String myValue = myjoin.getDataField("alias1.field1").asString();
    * Setting a field value:
    *

    * myjoin.setFieldValue("alias1.field2","abcdefg");
    * Retrieving search results:
    * myJoin.setFieldValue("alias1.field3", "ab%");

    * myJoin.setFieldValue("alias2.field2", "e%");

    * java.util.ArrayList results = 
myJoin.searchAndRetrieveList("alias1.field1")'

    *
    * This version searched for all records where table 1 field 3 starts 
with 'ab' and table 2 field 2, starts with 'e'. It then orders the results 
by table 1 field 1.
    * Clearing loaded fields
    * myJoin.clear();

    *


Accessing JoinedDataObjects in DBMaint

Since Expresso 5.1, DBMaint has been rewritten to manage any DataObject, 
whether it is backed by a database or an in-memory hashmap. So, of course, 
DBMaint can now handle displaying and managing JoinedDataObjects.

Traditionally, you launch DBMaint with the 'dbobj' parameter telling it 
what class to instantiate and use. But of course, JoinedDataObjects use the 
'Defineable' interface to uniquely retrieve their definition. To this end, 
the 'definition' parameter has been added to DBMaint's capability. The 
definition parameter is identical to that of what you set earlier when 
instantiating it by memory. So to list all records of the join, enter (all 
in one line)
/DBMaint.do?dbobj=com.jcorporate.expresso.core.dataobjects.jdbc.JoinedDataObject&definition=
/org/example/myapp/dbobj/myjoin.xml&state=List


-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mailman.jcorporate.com/pipermail/opensource/attachments/20030630/75d465ab/attachment-0002.htm


More information about the Opensource mailing list