db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From t...@apache.org
Subject cvs commit: jakarta-ojb/xdocs tutorial1.xml
Date Wed, 04 Dec 2002 21:03:22 GMT
thma        2002/12/04 13:03:22

  Modified:    xdocs    tutorial1.xml
  Log:
  style.enhance()
  
  Revision  Changes    Path
  1.12      +200 -123  jakarta-ojb/xdocs/tutorial1.xml
  
  Index: tutorial1.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-ojb/xdocs/tutorial1.xml,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- tutorial1.xml	31 Jul 2002 10:45:40 -0000	1.11
  +++ tutorial1.xml	4 Dec 2002 21:03:22 -0000	1.12
  @@ -3,6 +3,7 @@
   
     <properties>
       <author email="thma@apache.org">Thomas Mahler</author>
  +    <author email="tobrien@transolutions.net">Tim O'Brien</author>
       <title>ObJectRelationalBridge Tutorial - Part 1</title>
     </properties>
   
  @@ -20,64 +21,96 @@
       <B><code>org.apache.ojb.tutorial1</code></B>.
     </p>
     <p>
  -    I begin with explaining the application and outlining its
  -    architecture. After that I will explain how the
  -    ObJectRelationalBridge API can be used in the implementations of the
  -    use cases to perform persistence operations like retrieval, storage
  -    and deletion of objects. Finally I will show how the O/R mapping is
  -    built for the applications persistent class <code>Product</code>.
  +    This document explains the architecture of a simple application which 
  +    uses the ObJectRelationalBridge API (PersistenceBroker) to 
  +    implement five use cases which include persistence operations (retrieval, 
  +    storage, deletion of objects). This document will also demonstrate how a 
  +    simple persistence object <code>Product</code> is mapped to a table in

  +    a relational database.
     </p>
   </subsection>
   
  -<subsection name="The sample application">
  -  <p>
  -    The sample application is a console based data entry application.
  -    It's a product catalog database with simple use cases:
  -
  -    <ol>
  -      <li>
  -        List all Products in catalog (all Products entered in this or earlier
  -        sessions and did not get deleted must be displayed)
  -      </li>
  -      <li>
  -        Enter a new Product (the new Product must be made persistent)
  -      </li>
  -      <li>
  -        Edit an existing Product record
  -      </li>
  -      <li>
  -        Delete a Product record (the Product must be removed from the persistent
  -        store)
  -      </li>
  -      <li>
  -        To keep a homogenous design quitting the application is also modelled as
  -        a use case.
  -      </li>
  -    </ol>
  -
  -    These use case shall implement only a rudimentary functionality.
  -    Thus we don't have to care about special cases or variants.
  +<subsection name="The Tutorial Application">
  +  <p>
  +   The sample application is a console based data entry application -
  +   a program to manipulate a product catalog database with five simple
  +   use cases:
  +  </p>
  +
  +  <ol>
  +    <li>
  +      <b>List all Products</b> - 
  +      display all products from the persistent store.
  +    </li>
  +    <li>
  +      <b>Enter a new Product</b> -
  +      create a new product in the persistent store
  +    </li>
  +    <li>
  +      <b>Edit an existing Product record</b> -
  +      update a product in the persistent store
  +    </li>
  +    <li>
  +      <b>Delete a Product record</b> -
  +      remove a product from the persistent store
  +    </li>
  +    <li>
  +      <b>Quit the application</b> -
  +      for consistency we implement this as a use case
  +    </li>
  +  </ol>
  +
  +  <p>
  +  	Only these five basic use cases have been implemented in the
  +    interest of keeping this tutorial focused on conveying only the basic
  +    concepts of OJB.  This tutorial does not explain the necessary steps
  +    to model or implement 1:1, 1:n, or m:n mapping.  For information about
  +    this please refer to Tutorial 3 <a href="tutorial3.html">Advanced O/R</a>.
     </p>
   </subsection>
   
  -<subsection name="see it running...">
  +<subsection name="Running the Tutorial Application">
     
     <p>
  -	To see the tutorial application at work you first have to compile the sources
  -	and to setup the test database
  -  	by executing <code>bin\build prepare-tutorials</code> under Win32 or
  -  	<code>bin/build.sh prepare-tutorials</code> under Unix/Linux
  -  	from the ojb toplevel directory.
  - </p>
  +   To execute the application described in this tutorial,
  +   you must prepare the tutorials from the source distribution of
  +   OJB. This is accomplished via Ant build scripts which are executed
  +   by a script in the "bin" directory of the OJB distribution. (Note:
  +   This tutorial assumes that you have already downloaded the OJB
  +   source distribution.)  Note: There is no need to configure a
  +   database in order to run these applications.  The tutorial applications
  +   ship with HSQLDB integration, all you need to do is run the
  +   prepare-tutorials Ant target.
  +  </p>
  +
  +  <p> 
  +   Unpack the OJB source distribution, make sure that your current
  +   working directory is the top level directory of the OJB
  +   distribution and run the following script:
  +  </p>
  +   
  +  <ul>
  +   <li>On Windows 9x/NT/2000/XP:
  +    <ul>
  +     <li><b>Prepare the Tutorials:</b> 
  +         <code>bin\build.bat prepare-tutorials</code></li>
  +     <li><b>Execute this Tutorial:</b>
  +         <code>bin\tutorial1.bat</code></li>
  +    </ul>
  +   </li>
  +   <li>On Unix/Linux:
  +    <ul>
  +     <li><b>Prepare the Tutorials:</b> 
  +         <code>bin/build.sh prepare-tutorials</code></li>
  +     <li><b>Execute this Tutorial:</b> 
  +         <code>bin/tutorial1.bat</code></li>
  +    </ul>
  +   </li>
  +  </ul>
   
  -  <p>
  -    Now you can start the tutorial application by executing
  -    <code>bin\tutorial1</code> or <code>bin/tutorial1.sh</code>
  -    from the ojb toplevel directory.
  -  </p>
   </subsection>
   
  -<subsection name="Architectural scetch">
  +<subsection name="Tutorial Application Architecture">
     <p>
       The overall architecture of the application is outlined in the
       class diagram below.
  @@ -89,8 +122,7 @@
       provides some convenience code useful for all concrete
       implementations. There are four concrete UseCase Implementations:
       UCListAllProducts, UCEnterNewProduct, UCDeleteProduct and
  -    UCQuitApplication. These concrete classes implement the functionality
  -    of the above mentioned Use Cases. The class <code>Product</code>
  +    UCQuitApplication. The class <code>Product</code>
       represents a product entry in the product database and is the only
       persistent class in this application.<br/><br/><br/>
     </p>
  @@ -99,14 +131,15 @@
       <br/><br/>
     </p>
     <p>
  -    figure 1: Class Diagram with the application classes of the
  +    Figure 1: Class Diagram with the application classes of the
       tutorial application
     </p>
     <p>
  -    The Application::run() method runs a non-terminating driver loop.
  -    It does the following: let the user select a use case and perform
  -    this use case and so forth:
  -  </p>
  +    The <code>Application.run()</code> method runs a main event loop. The
  +    program waits for user input in <code>Application.selectUserCase()</code>.
  +    Once a UseCase is selected, it is executed via the 
  +    <code>UseCase.apply()</code> method.  This UseCase class is a simple
  +    implementation of the well-known Command design pattern.</p>
     <source><![CDATA[
       while (true)
       {
  @@ -123,16 +156,18 @@
       }
     ]]></source>
     <p>
  -    A UseCase must implement two methods: <code>getDescription()</code> and
  -    <code>apply()</code>. <code>UseCase::getDescription()</code>
is used to
  -    display a short information on the use case. This method is used in
  -    <code>Application::selectUseCase()</code> to display each use case.
  -    <code>UseCase::apply()</code> performs the business logic implemented by
the
  -    use case.
  +    The UseCase interface contains two methods: <code>getDescription()</code>

  +    and <code>apply()</code>. <code>UseCase.getDescription()</code>
is used 
  +    to display a short description of the use case to the user. 
  +    This method is used in <code>Application.selectUseCase()</code> to 
  +    display each use case in a menu. <code>UseCase.apply()</code> performs

  +    the business logic implemented by the specific implementation of 
  +    <code>UseCase</code>.
     </p>
     <p>
  -    Let's start with the most simple use case: <code>UCQuitApplication</code>.
  -    Here is its <code>apply()</code> method:
  +    Starting with the simplest use case in our application - 
  +    <code>UCQuitApplication</code>. Here is the <code>apply()</code>
method
  +    from the quit application use case:
     </p>
     <source><![CDATA[
       public void apply()
  @@ -144,37 +179,48 @@
   </subsection>
   </section>
   
  -<section name="Using the OJB PersistenceBroker API in the UseCase implementations">
  +<section name="Using the OJB PersistenceBroker API in the UseCase Implementations">
     <p>
  -    Ok, that was rather trivial as no persistence operations were
  -    involved. Now to some real work: <code>UCListAllProducts</code>.
  -    This use case must lookup a Collection containing all products from
  -    the persistent storage. Then it must iterate over this collection and
  -    print each product. <br/>
  -    To lookup the collection from the persistent
  -    storage we need a method from the OJB API. OJB provides three major
  -    APIs. The PersistenceBroker, ODMG implementation, and JDO implementation. In this
  -    first tutorial I will only use the PersistenceBroker API as it is
  -    simpler to use. <a HREF="tutorial2.html">Using the ODMG API</a> and
  -    <a href="tutorial4.html">Using the JDO API</a> are
  -    covered in separate tutorials.
  +    The code example above was trivial - there are no persistence operations 
  +    involved in quitting the application.  Let's move on to a more relevant
  +    example - <code>UCListAllProducts</code>.
  +    This use case must retreive a <code>Collection</code> containing all 
  +    products from the database. It must then iterate over this collection 
  +    and print each product.To retreive the collection from the database we need a method
from the 
  +    OJB API.
  +  </p> 
  +  
  +  <p><b>OJB provides three major APIs.</b></p>
  +  
  +  <ul>
  +   <li>The PersistenceBroker</li>
  +   <li>An ODMG implementation</li>
  +   <li>A JDO implementation</li>
  +  </ul>
  +   
  +  <p>
  +    In this first tutorial only the <b>PersistenceBroker API</b> is used as
it 
  +  	is the most straightforward of the three options. Tutorial 2: 
  +  	<a HREF="tutorial2.html">Using the ODMG API</a> and
  +    Tutorial 4: <a href="tutorial4.html">Using the JDO API</a> will 
  +    implement the same application using these different methods of
  +    database access.  
     </p>
     <p>
       You will find the source for the PersistenceBroker API in the
       package <code>org.apache.ojb.broker</code>. <A HREF="javadoc/ojb/broker/package-summary.html">The
  -    JavaDoc is here</A>. The Most important part of this API is the
  +    JavaDoc is here</A>. The key component in this package is the
       interface <code>PersistenceBroker</code>. It
       provides methods for retrieval, storage and deletion of objects. To
       use it in your application you must know how to retrieve a Broker
       instance, how to configure its O/R mapping repository and how to use
  -    its API.
  +    the available functionsI.
     </p>
   
  -  <subsection name="Obtaining a broker instance">
  +  <subsection name="Obtaining a Broker Instance">
     <p>
  -    To learn how to obtain a Broker instance lets have a look at the
  -    Application class. The public constructor of this class looks like
  -    follows:
  +    How do we obtain a Broker instance? Take a look at the public constructor
  +    of the Application class to find the answer to this question.
     </p>
     <source><![CDATA[
       public Application()
  @@ -197,29 +243,28 @@
       }
     ]]></source>
     <p>
  -    We just ask the PersistenceBrokerFactory to create an instance that
  -    uses the file ./repository.xml as mapping repository (more details on
  -    this repository in the <A HREF="#def_or">section on the Object
  -    /Relational mapping</A>). This broker instance is reached to the
  -    constructors of the UseCases. The constructors just store it in a
  -    protected attribute <code>broker</code> for
  -    further usage.
  +    The PersistenceBrokerFactory creates an instance of PersistenceBroker
  +    using the resource ./repository.xml as a mapping repository (more
  +    details on this repository in the <A HREF="#def_or">section on the
  +    Object/Relational mapping</A>. The PersistenceBroker instance is
  +    passed to the constructor of the four UseCase objects which
  +    store this PersistenceBroker instance as a protected member variable.
     </p>
     </subsection>
  -<subsection name="Retrieving collections and iterators">
  + <subsection name="Retrieving Collections and Iterators">
     <p>
  -    The next thing we need to know is how to use this broker instance to help us
  -    in our persistence operations. In this use case we have to retrieve a
  -    collection containing all product entries from the persistent store. To
  +    The next thing we need to know is how to use this broker instance to implement
  +    our persistence operations. In this use case, we have to retrieve a
  +    collection containing all product entries from the database. To
       retrieve a collection containing objects matching some criteria we can use
  -    <code>PersistenceBroker::getCollectionByQuery(Query query)</code>.
  -    Where <code>Query</code> is a Class that allows to formulate criteria like
  -    price &gt; 100. In our case we want to select <I>all</I> persistent
  -    instances, so we need no filtering criteria, they can thus be left
  -    <code>null</code>.
  +    <code>PersistenceBroker.getCollectionByQuery(Query query)</code>.
  +    Where <code>Query</code> is a class that allows to specify criteria like
  +    price &gt; 100 or userId == 3. In our case we want to select <I>all</I>

  +	of the persistence objects stored in the Product table.  We need <b>no</b>

  +	(or <i>null</i>) filtering criteria.
     </p>
     <p>
  -    Here is the code of the <code>UCListAllProducts::apply()</code>method:
  +    Here is the code of the <code>UCListAllProducts.apply()</code>method:
     </p>
   
     <source><![CDATA[
  @@ -249,17 +294,24 @@
     ]]></source>
   
     <p>
  -    If you don't need the resulting collection for further reference as in this
  -    example where we just want to iterate over all products once, it may be a
  -    good idea not to use getCollectionByQuery() but getIteratorByQuery() which
  -    returns an Iterator.
  -  </p>
  -  <p>
  -    This method is extremely useful if you write applications that have to
  -    iterate over large resultsets. Instances are not created all at once but
  -    only on demand, and instances that are not longer referenced by the
  -    application my be reclaimed by the garbage collector. Using this method the
  -    code will look like follows:
  +   Imagine that there are 10,000 products in the product table:
  +   Retrieving a collection of all Products from the persistent store
  +   would be a very expensive operation - new objects are created and an
  +   entire table is loaded into memory.  In this tutorial application,
  +   performance is not a major issue, but in a real-world application OJB
  +   provides a more efficient mechanism for iterating through all the
  +   available products.  If your application does not need to maintain a
  +   collection of product objects in memory, you should call
  +   getIteratorByQuery() which returns an Iterator instead of a Collection.
  +  </p>
  +  <p>
  +    This method is extremely useful if you write applications that
  +    need to iterate over large resultsets. Instances are not created
  +    all at once, they are created on an "as needed" basis as you
  +    iterate through the result.  Instances of persistent objects which
  +    are no longer referenced by the application can be reclaimed by
  +    the garbage collector. Using this method the code will resemble
  +    the following:
     </p>
   
     <source><![CDATA[
  @@ -273,7 +325,7 @@
           try
           {
               // ask the broker to retrieve an Iterator
  -            java.util.Iterator iter = broker.getIteratorB
  +            java.util.Iterator iter = broker.getIteratorByQuery(query);
               // now iterate over the result to print each product
               while (iter.hasNext())
               {
  @@ -301,7 +353,7 @@
   product's data (productname, price and available stock). These data
   is stored in the new objects attributes. Then we must store the newly
   created object in the persistent store. We can use the method
  -<code>PersistenceBroker::store(Object obj)</code>
  +<code>PersistenceBroker.store(Object obj)</code>
   for this task.
   </p>
     <source><![CDATA[
  @@ -349,14 +401,33 @@
   
   </subsection>
   <subsection name="Updating Objects">
  +
     <p>
  -    Editing and updating a product entry works quite similar. The user
  -    enters the products unique id and the broker tries to lookup the
  -    respective object. This lookup is necessary as our application does
  -    not hold a list of all products. The found product is then edited and
  -    then stored. The PersistenceBroker uses the <code>.store(...)</code>
  -    method for inserting new objects as well as for updating existing
  -    objects. Here is the code:
  +   When a user wants to edit a product ( by selecting item #2 from the
  +   menu ), a user must first enter the "id" of the product to be
  +   edited.  Since the application does not maintain a list of product
  +   objects, the system must first retrieve a product from persistent
  +   storage via the PersistenceBroker.
  +  </p>
  + 
  +  <p>
  +   Selecting an object from the PersistenceBroker is simple - we must
  +   first create a QueryByExample object.  A QueryByExample object is
  +   created with a new Product object that contains an "id" property
  +   which has been populated with the id the user supplied.  You will
  +   notice that all of the other properties of the Product object
  +   remain unpopulated. We have essentially defined a filter by
  +   specifying our desire for a Product object that matches this
  +   product id.
  +  </p>
  + 
  +  <p>
  +   The Product object is retrieved, with the call to
  +   <code>broker.getObjectByQuery(query)</code>.  This retreived object is then
  +   edited by setting properties based on the user input, and this
  +   object is then stored in the persistence storage through a call to
  +   <code>broker.store(toBeEdited)</code>.  Here is the code from 
  +   <code>UCEditProduct</code>.
     </p>
   
     <source><![CDATA[
  @@ -468,7 +539,13 @@
     ]]></source>
   
   </subsection>
  -<subsection name="Finishing this application is left as an exercise to the interested
reader">
  +<subsection name="Completing the Tutorial Application">
  +
  +  <p>
  +   The completion of this tutorial program is left as an exercise for
  +   the tutorial reader.
  +  </p>
  +
   
     <p>
       Now you are familiar with the basic functionalities of the OJB
  @@ -530,7 +607,7 @@
       In the following sections I will show how the O/R mapping is
       defined for the tutorial application.
     </p>
  -<subsection name="the persistent class Product">
  +<subsection name="A Persistent Class: Product">
     <p>
       There is only one persistent class in our tutorial application,
       the class <code>Product</code>. Here it's definition:
  @@ -560,7 +637,7 @@
     </p>
   </subsection>
   
  -<subsection name="The corresponding database table">
  +<subsection name="The Product Database Table">
     <p>
       Now we take a look at a corresponding table definition, in SQL DDL
       (I give the instantDB syntax here, the syntax may vary slightly for
  @@ -628,7 +705,7 @@
   
   </subsection>
   
  -<subsection name="The Mapping">
  +<subsection name="The Product Mapping">
   <p>
   Now we have to describe the mapping from the class <code>Product</code>
   to the database table <code>PRODUCT</code>. This
  @@ -812,7 +889,7 @@
   	<a href="repository.html">found here</a>.
   </p>
   </subsection>
  -<subsection name="tool support">
  +<subsection name="Tool Support">
   <p>
   Generally speaking there are three approaches in building an O/R mapping:
   </p>
  
  
  

Mime
View raw message