Using Castor JDO for SQL Mapping

Using Castor JDO for SQL Mapping

Many-to-many Relationship

In order to properly represent many-to-many relationships in a database, an intersection table is required. An intersection table consists of two foreign key columns, one for each table in the many-to-many relation. Each column may have the same key value repeated in the table rows, although identical foreign key pairings should not appear in more than one row of the table.

Let's say that each PortOfCall keeps track of the Ships that visit it, in addition to each Ship maintaining its own PortOfCall list. Each PortOfCall sees many Ships, each Ship enters many PortsOfCall. This is our many-to-many relation.

I might only have two Java classes, but I will have three database tables to store these two classes. First, an outline of the Java classes is in order:

public class Ship

{

   String name;

  // String registry;  // commented out 

   ArrayList portsOfCall = new ArrayList();



   public Ship() { ... }



   public void addPortOfCall( PortOfCall poc )

   {

     portsOfCall.add( poc );

     poc.addShip( this );

   }



   //other methods...

} 



public class PortOfCall

{

   String name;

   ArrayList ships = new ArrayList;



   public PortOfCall() { ... }



   public void addShip( Ship ship )

   {

     portsOfCall.add( ship );

   }

 

   // other methods...

}

Note: Since they're not pertininent to the present discussion, I haven't shown how a ship's arrival and departure times figure into these two classes. Assume they are somehow associated with the Ship's PortOfCall instances.

Due to a limitation in the current version of Castor, I've had to rely on name alone to identify a Ship. The mapping files for both Ship and PortOfCall are as follows:

<class name="Ship" identity="name" depends="ShippingLine">

  <map-to table="ship"/> 

  <field name="registry" type="string" required="true">

    <sql name="registry" type="varchar"/>

  </field> 

  <field name="name" type="string" required="true"> 

    <sql name="name" type="varchar"/>

  </field> 

<field name="shippingLine" type="ShippingLine" required="true"> 

    <sql name="id_shipping_line"/> 

  </field>

  <field name="portOfCall" type="PortOfCall" collection="arraylist">

     <sql name="poc_name" many-table="poc_ship" many-key="ship_name"/>

  </field>

</class>



<class name="com.example.shipping.PortOfCall" identity="name">

   <map-to table="port_of_call"/>

   <field name="name" type="string"> 

     <sql name="name" type="varchar"/> 

   </field>  

   <field name="ship" type="Ship" collection="arraylist">

     <sql name="ship_name" many-table="poc_ship" many-key="poc_name"/> 

   </field> 

</class>

Nothing need be changed in the ship table, and the port_of_call table is simple enough:

CREATE TABLE port_of_call ( 

   name VARCHAR(80) 

); 

I now have to add a third join table, poc_ship, that links many port_of_call rows to many ship rows through their respective foreign keys (as described in the mapping file):

CREATE TABLE poc_ship ( 

   poc_name VARCHAR(80),    -- port_of_call fkey 

   ship_name VARCHAR(80)    -- ship fkey

 );

It's now possible to construct a test case, part of which is shown below:

...

ship[0].setName("Seven Seas");

ship[1].setName("Sea Six");



_shippingLine.addShip( ship[0] );

_shippingLine.addShip( ship[1] );  



PortOfCall pocs[] = new PortOfCall[]

{

   new PortOfCall("Pago Pago"), 

   new PortOfCall("Walla Walla")

}; 



ship[0].addPortOfCall( _poc[0] ); 

ship[0].addPortOfCall( _poc[1] );



ship[1].addPortOfCall( _poc[0] );

...

PersistenceFactory.getInstance().store(pocs[0], true); 

// true means create, not update

PersistenceFactory.getInstance().store(pocs[1], true);

//stores all Ships instances as well

PersistenceFactory.getInstance().store(_shippingLine, true); 

Now, if all went according to plan, I should see entries in the poc_ship table when I execute a SELECT * from poc_ship; SQL statement from the DBMS's command line:

poc_name     | ship_name

----------------------------

Pago Pago    | Sea Six

Walla Walla  | Sea Six

Pago Pago    | Seven Seas

If I see these entries, then I know I've successfully recorded a many-to-many join in the database using Castor JDO.

Making the Connection

In order to be able to access the database, we need to establish a connection to it. Castor maintains connection information in a separate file from the mapping file. This file is typically named database.xml.

The database.xml file contains information about the database being used and its location. It also indicates the JDBC driver to be used (JDBC stands for Java Database Connectivity, an vendor-neutral API for communicating with relational database management systems).

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor JDO Configuration DTD

     Version 1.0//EN" "http://castor.exolab.org/jdo-conf.dtd">

<database name="shippingDB" engine="postgresql"> 

   <driver class-name="org.postgresql.Driver" url="jdbc:postgresql:shippingDB">  

      <param name="user" value="Administrator"/>

      <param name="password" value=""/> 

   </driver>    

   <mapping href="d:/shipping/mapping.xml" />

</database>

The database to connect to is indicated by the value of the name attribute in the database element. The engine attribute of that element tells Castor that it's a Postgres database (formerly known as PostgreSQL, hence the name of the Castor database engine).

The driver element has a class-name attribute that indicates the class in the Java classpath that functions as the JDBC driver. The url attribute is the connection string that the JDBC driver uses to make a connection to the Postgres database. A JDBC driver is often supplied by the database vendor or distributor. For Postgres, an up-to-date JDBC driver can be found at http://jdbc.postgresql.org.

The param elements have user and password information that the driver needs to log in to the database. Other JDBC drivers may have more (or possibly fewer) parameters, so additional param elements can be provided as children of the driver element.

Finally, the location of the JDO mapping file is given in href format. Once the JDBC connection is established, Castor reads in the mapping.xml file and is ready to start storing and retrieving data.

Prev  [1] [2] [3] [4] [5] [6] [7] Next

Close    To Top
  • Prev Article-Java:
  • Next Article-Java:
  • Now: Tutorial for Web and Software Design > Java > JDOnJDBCnSQLJ > Java Content
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Geek Tutorial
     

    Blogging Tutorial

      RSS Tutorial
      Podcasting Tutorial
    Graphic Design Tutorial
      Coreldraw Tutorial
      Illustrator Tutorial
      3D Tutorials
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial/ Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial/ Articles
     

    XML Style

      AJAX Tutorial
      XML Mobile
    Flash Tutorial/ Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial/ Articles
      Linux Tutorial
      Symbian Tutorial
      MacOS Tutorial
    Personal Tech
      Hardware Tutorial
      Software Tutorial
      Online Auction