[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