Mapping between tables and XML documents
    We describe the above by using an example. Let's assume we
      have a table "httpSession" in which we store the sessions
      of an HTTP servers current users. Each user has choosen a
      language in which he wants his HTML pages to be displayed.
      Thus we have the following tables:
    
      CREATE TABLE language (
        id INT NOT NULL IDENTITY,
        language VARCHAR(10) NOT NULL,
        country VARCHAR(10) NOT NULL,
        PRIMARY KEY (id),
        UNIQUE (language, country)
      );
      CREATE TABLE httpSession (
        id INT NOT NULL IDENTITY,
        ipaddress VARCHAR(15) NOT NULL,
        logintime TIMESTAMP NOT NULL,
        lastaction TIMESTAMP NOT NULL,
        expiretime SMALLINT NOT NULL,
        cookie VARCHAR(25) NOT NULL,
        languageid INT NOT NULL,
        PRIMARY KEY (id),
        UNIQUE (cookie),
        FOREIGN KEY (languageid) REFERENCES language (id)
      );
    
    
    A Schema for JDBC mapping
    This situation is just what JaxMe was made for: The secondary
      table "language" will typically be subject to manual modifications
      only. The "httpSession" table, however, is updated all the time.
    To access these tables, we again create some kind of XML schema:
    
      <?xml version="1.0" encoding="UTF-8"?>
      <xs:schema
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          targetNamespace="http://jaxme.ispsoft.de/namespaces/examples/Session"
          xmlns:jm="http://ispsoft.de/namespaces/jaxme/schema"
          xmlns:jdbcm="http://ispsoft.de/namespaces/jaxme/jdbc-mapping">
        <xs:annotation>
          <xs:appinfo>
            <jm:defaults package="com.mycompany.session"/>
            <jdbcm:defaults driver="org.hsqldb.jdbcDriver"
                url="jdbc:hsqldb:build/db/db"
                user="sa" password=""/>
          </xs:appinfo>
        </xs:annotation>
        <xs:element name="Session">
          <xs:annotation>
            <xs:appinfo>
              <jdbcm:select
                tables="httpSession JOIN language ON httpSession.languageid=language.id"
                />
              <jdbcm:table name="httpSession"/>
            </xs:appinfo>
          </xs:annotation>
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Language">
                <xs:annotation>
                  <xs:appinfo>
                    <jdbcm:table name="language"/>
                  </xs:appinfo>
                </xs:annotation>
                <xs:complexType>
                  <xs:sequence/>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:schema>
    
    Now suggest the following row in the "httpSession" table:
    But now, how do we get this? We'll use some examples to demonstrate
      working with the Session document.
    
    Creating classes for JDBC
    Using the source generator is not so different. In short, you
      have to change the SchemaReader and SourceGenerator:
    
      java de.ispsoft.jaxme.generator.Main Session.xsd
        --schemaReader=de.ispsoft.jaxme.generator.XsdJdbcSchemaReader
        --sourceWriter=de.ispsoft.jaxme.generator.JdbcJavaSourceWriter
    
    As before, you will find classes "ClsSession", "ClsSessionHandler",
      "ClsLanguage" and "ClsLanguageHandler" being generated. But this
      time, there is an additional class "ClsSessionManager". It is
      responsible for access to the database.
    Note: If you are using an Oracle database, you might
      need an additional argument
      
        --option=jdbc.dbmode=Oracle
      
    
    
    Reading data from a relational database
    First of all, we have to specify database driver, JDBC URL,
    user name and password, like in any other JDBC application. This
    is done in an XML file:
    
      <?xml version="1.0" encoding="UTF-8" ?>
      <JMManagerConfiguration
          xmlns="http://jaxme.ispsoft.de/namespaces/JMManagerConfiguration">
        <Defaults>
          <JMJdbcManager>
            <Driver>org.hsqldb.jdbcDriver</Driver>
            <Url>jdbc:hsqldb:build/db/db</Url>
            <User>sa</User>
            <Password/>
          </JMJdbcManager>
        </Defaults>
        <Configuration
            localName="Session"
            namespaceURI="http://jaxme.ispsoft.de/namespaces/examples/Session">
          <ManagerClass>com.mycompany.session.ClsSessionManager</ManagerClass>
          <ElementClass>com.mycompany.session.ClsSession</ElementClass>
          <HandlerClass>com.mycompany.session.ClsSessionHandler</HandlerClass>
        </Configuration>
      </JMManagerConfiguration>
   
    Note that the given values are just defaults and can be overwritten
    per document type by adding subelements Driver, Url,
    and so on to the respective Configuration section. For
    example, to use the same settings for the Session Document,
    but a different user name, you would use
    
        <Configuration
            localName="Session"
            namespaceURI="http://jaxme.ispsoft.de/namespaces/examples/Session">
          <ManagerClass>com.mycompany.session.ClsSessionManager</ManagerClass>
          <ElementClass>com.mycompany.session.ClsSession</ElementClass>
          <HandlerClass>com.mycompany.session.ClsSessionHandler</HandlerClass>
          <User>otheruser</User>
        </Configuration>
    
    This file is best inserted into your classpath somewhere, for example,
      as a part of a JAR file. Assuming, that your configuration file is
      in com/mycompany/Configuration.xml, you could write the
      following program, that writes all current HTTP sessions to System.out,
      much like the "AddressPrinter":
    
import com.mycompany.session.ClsSession;
import de.ispsoft.jaxme.*;
public class SessionPrinter {
  public static void main(String[] args) throws Exception {
    System.setProperty(JMFactory.URI_PROPERTY,
                       "resource:com/mycompany/Configuration.xml");
    JMManagerFactory factory = JMFactory.getJMManagerFactory();
    JMManager manager = factory.getManager(ClsSession.NAMESPACE_URI,
                                           ClsSession.LOCAL_NAME);
    String query = "LASTACTION + EXPIRETIME > NOW()";  // A WHERE clause
    for (java.util.Iterator iter = manager.select(query);
         iter.hasNext();  ) {
      ClsSession session = (ClsSession) iter.next();
      System.out.println(session.toXML());
    }
  }
}
    
    You could also read the configuration from a file or URL by changing
      the property value to
    
      file://c:\temp\Configuration.xml
    
      or
    
      http://configurations.company.com/Configuration.xml
    
    And you could, of course, specify the property value from the command
    line and not within the program.For details, see the
    
    Writing data to a relational database
    Now an example that creates a new HTTP session. It uses
      the same property file as before:
    
import com.mycompany.session.ClsSession;
import de.ispsoft.jaxme.*;
public class SessionAdd {
  public static void main(String[] args) throws Exception {
    System.setProperty(JMFactory.URI_PROPERTY,
                       "resource:com/mycompany/Configuration.xml");
    JMManagerFactory factory = JMFactory.getJMManagerFactory();
    JMManager manager = factory.getManager(ClsSession.NAMESPACE_URI,
                                           ClsSession.LOCAL_NAME);
    ClsSession session = (ClsSession) manager.create();
    session.eID = new Integer(126776);
    session.eIPADDRESS = "134.23.1.7";
    session.eLOGINTIME = new java.sql.Timestamp(System.currentTimeMillis());
    session.eLASTACTION = session.eLOGINTIME;
    session.eEXPIRETIME = new Short((short) (15*60));
    session.eCOOKIE = "jH63fGdx";
    session.eLANGUAGEID = new Integer(3);
    manager.insert(session);
  }
}
    
    A similar example, the update of a row:
    
import com.mycompany.session.ClsSession;
import de.ispsoft.jaxme.*;
public class SessionUpdate {
  public static void main(String[] args) throws Exception {
    System.setProperty(JmFactory.URI_PROPERTY,
                       "resource:com/mycompany/Configuration.xml");
    JMManagerFactory factory = JMFactory.getJMManagerFactory();
    JMManager manager = factory.getManager(ClsSession.NAMESPACE_URI,
                                           ClsSession.LOCAL_NAME);
    java.util.Iterator iter = manager.select("COOKIE='jH63fGdx'");
    if (iter.hasNext()) {
      ClsSession session = (ClsSession) iter.next();
      session.eLASTACTION = new java.sql.Timestamp(System.currentTimeMillis());
      manager.update(session);
    }
  }
}
   
   And finally, as you have probably guessed, an example for
     deleting a row:
    
import com.mycompany.session.ClsSession;
import de.ispsoft.jaxme.*;
public class SessionDelete {
  public static void main(String[] args) throws Exception {
    System.setProperty(JMFactory.URI_PROPERTY,
                       "resource:com/mycompany/Configuration.xml");
    JMManagerFactory factory = JMFactory.getJMManagerFactory();
    JMManager manager = factory.getManager(ClsSession.NAMESPACE_URI,
                                           ClsSession.LOCAL_NAME);
    java.util.Iterator iter = manager.select("COOKIE='jH63fGdx'");
    if (iter.hasNext()) {
      ClsSession session = (ClsSession) iter.next();
      manager.delete(session);
    }
  }
}
   
   
   Creating a primary key for immediate use
   If you want to create a primary key that should be used
     immediately after the INSERT statement, then you have to
     specify an additional SELECT statement. For example:
   
     <jdm:table name="httpSession" keys="ID">
       <jdm:createKeyQuery>
         SELECT httpSessionSequence.nextval()
       </jdm:createKeyQuery>
     </jdm:table>
   
    The above example would issue the SELECT statement before an
    insert. The generated value would be written into the ID
    column. Finally the INSERT statement would be performed.
    Once the operation is done, the application could access the
    generated value in the ID column.
  In some cases the order of INSERT and SELECT has to be
    reversed. For example the MySQL database has a nice feature
    called autoincrement column. With autoincrement columns the
    above example might look like
  
     <jdm:table name="httpSession" keys="ID">
       <jdm:createKeyQuery postInsert="true">
         SELECT LAST_INSERT_ID()
       </jdm:createKeyQuery>
     </jdm:table>
  
    This example would work quite the same, except that the
    SELECT statement would be performed after the INSERT. (postInsert)
    Again, the application might read the generated value from
    the ID column.
  For combined keys the example could work quite the same.
    The only difference would be, that the SELECT statement had
    to return multiple values, one for each column.
  TODO: Provide an example for createKeyQuery.
  
   Find methods
   In most cases you would like to specify certain fixed queries,
     that are performed frequently. This is possible by specifying
     find methods:
     
       <jdbcm:select
         tables="httpSession JOIN language ON httpSession.languageid=language.id"
         />
         <jdbcm:findMethod name="findByIpAddress" query="IPADDRESS = ?">
           <jdbcm:param name="pIpAddress" type="xs:string"/>
         </jdbcm:findMethod>
         <jdbcm:findMethod name="findByLanguageId" query="LANGUAGEID = ?"
           maxResultSize="1">
           <jdbcm:param name="pLanguage" type="xs:integer"/>
         </jdbcm:findMethod>
       <jdbcm:table name="httpSession"/>
     
     In the above case the generated manager would have additional methods
     
       java.util.List findByIpAddress(String pIpAddress);
       ClsSession findByLanguage(Integer pLanguage);
     
     These are mainly shortcuts for
     
       java.util.List select("IPADDRESS = ?",
                             new Object[]{JMManager.VARCHAR, pIpAddress});
       java.util.List select("LANGUAGE = ?",
                             new Object[]{JMManager.INTEGER, pLanguage});
     
     However, note that in the findByLanguage example the interface is
     specified to return a single instance, which is much more convenient.
     It is also possible to specify an attribute minResultSize.
     This would throw a SAX exception, if the generated result size is
     below the given number.
     Find methods are particularly useful in conjunction with the
     BeanWriter: The generated entity beans have the same find methods,
     that the manager has.
     As in the case of the views, find methods may have a dynamic
     part:
       
         <jdbcm:findMethod name="findByMatchingColumn"
           query="{MatchColumn} LIKE ?">
           <jdbcm:pattern name="pMatchColumn" sample="SomeColumn"
             match="{MatchColumn}/>
           <jdbcm:param name="pValue" type="xs:integer"/>
         </jdbcm:findMethod>
       
     And, of course, you may also make use of additional placeholder
     values:
       
         <jdbcm:findMethod name="findByWhatever"
           query="{Whatever}">
           <jdbcm:pattern name="pWhatever" sample="1=1"
             match="{Whatever}/>
           <jdbcm:placeholders name="pValues"/>
         </jdbcm:findMethod>
       
   
   Mapping between column names and elements or attributes
   By default the generator maps table columns to elements
     or attributes with the same name. If a matching element
     or attribute cannot be found, it creates one. This is
     convenient, but in most cases not what you actually want.
   The main problem is that the generator sees column names
     in all uppercase letters. (This is how most RDBMS supply
     their metadata.) But you don't want your attribute be called
     IPADDRESS, you want IpAddress. This can be fixed by
     explicitly specifying a certain spelling:
    
        <xs:element name="Session">
          <xs:annotation>
            <xs:appinfo>
              <jdbcm:table name="httpSession"/>
            </xs:appinfo>
          </xs:annotation>
          <xs:complexType>
            <xs:sequence>
	      <element name="Id"/>
	      <element name="Language"/>
	      <element name="Country"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:schema>
    
    This example will generate a class ClsSession with elements
      Id, Language and Country,
      mapped to the columns with the same names. Originally the
      elements have been named ID, LANGUAGE
      and COUNTRY, so that looks much better now.
    However, we are still not satisfied. What it we want the
      element Country to have the name
      CountryCode? This can be done by using an
      jdm:column clause:
    
        <xs:element name="Session">
          <xs:annotation>
            <xs:appinfo>
              <jdbcm:table name="httpSession"/>
            </xs:appinfo>
          </xs:annotation>
          <xs:complexType>
            <xs:sequence>
	      <element name="Id"/>
	      <element name="Language"/>
	      <element name="CountryCode">
	        <xs:annotation>
		  <xs:appinfo>
		    <jdbcm:column name="Country">
		  </xs:appinfo>
		</xs:annotation>
	      </element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:schema>
    
   
   Mapping of table names
   Table name mapping is a feature which you will use very rarely. It is best explained
     by looking at an instance of the "organization" document, as specified in the
     ../examples/misc/jdbcref.xsd
     example:
  <organization id="4" name="Foo Inc." emailId="3">
    <email id="3" emailAddress="a3@foo.com"/>
    <person id="57" fullName="Smith, Harry" emailId="2">
      </email id="2" emailAddress="a2@foo.com"/>
    </person>
  </organization>
     The example uses three tables: "organization", "person", and "email". The important
     point is that the "email" table is being used twice: It is referenced by both the
     "organization" and "person" tables.
   But why is this causing trouble? To understand that point, we take a look at the
     definition of the person document:
  <xs:element name="person">
    <xs:annotation>
      <xs:appinfo>
        <jdm:table name="Person"/>
        <jdm:select tables="Person left outer join Email on Person.emailId=Email.Id"/>
      </xs:appinfo>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence><xs:element ref="email"/></xs:sequence>
      <xs:attribute name="id"/>
      <xs:attribute name="fullName"/>
      <xs:attribute name="emailId"/>
    </xs:complexType>
  </xs:element>
     To read instances of this document, JaxMe will generate the following query:
  SELECT EMAIL.ID, EMAIL.EMAILADDRESS, PERSON.ID, PERSON.FULLNAME, PERSON.EMAILID
    FROM Person left outer join Email on Person.emailId=Email.Id
    In other words: It takes the table and column names, and creates a list
    of these names. But in the case of the "organization" table, this
    list would look like the following:
  SELECT EMAIL.ID, EMAIL.EMAILADDRESS, EMAIL.ID, EMAIL.EMAILADDRESS, PERSON.ID,
      PERSON.FULLNAME, PERSON.EMAILID, ORGANIZATION.ID, ORGANIZATION.NAME,
      ORGANIZATION.EMAILID, ORGANIZATION.PERSONID FROM Organization left
      outer join Email on Person.emailId=Email.id left outer join Person
      on Organization.personId=Person.id left outer join Email on
      Person.emailId=Email.id
    The first pair of EMAIL.ID and EMAIL.EMAILADDRESS would be to read the
    organizations email address, and the second pair is reading the
    persons. But this is obviously wrong, because they would always be the
    same!
  To fix the problem, SQL suggests the use of a table alias. The above
    query is fine, if we reformulate it as follows:
  SELECT EMAIL.ID, EMAIL.EMAILADDRESS, Email0.ID, Email0.EMAILADDRESS, PERSON.ID,
      PERSON.FULLNAME, PERSON.EMAILID, ORGANIZATION.ID, ORGANIZATION.NAME,
      ORGANIZATION.EMAILID, ORGANIZATION.PERSONID FROM Organization left
      outer join Email on Person.emailId=Email.id left outer join Person
      on Organization.personId=Person.id left outer join Email as Email0 on
      Person.emailId=Email0.id
    And this is exactly what JaxMe assumes: If the same table name
    tableName is used multiple times in a single, complex
    document, then the generator will use the aliases tableName0,
    tableName1, ... for the second, third, ... instance. In
    other words, a proper declaration of the "organization" document would
    look like this:
  <xs:element name="organization">
    <xs:annotation>
      <xs:appinfo>
        <jdm:table name="Organization"/>
        <jdm:select
          tables="Organization left outer join Email on Organization.emailId=Email.Id
                               left outer join Person on Organization.personId=Person.Id
                               left outer join Email AS Email0 on Person.emailId=Email0.Id"/>
      </xs:appinfo>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="email"/>
        <xs:element ref="person"/>
      </xs:sequence>
      <xs:attribute name="id"/>
      <xs:attribute name="name"/>
      <xs:attribute name="emailId"/>
      <xs:attribute name="personId"/>
    </xs:complexType>
  </xs:element>