Version 2

    Relationships

    The entity tutorial only showed one-to-many and many-to-one relationships.  This tutorial will show you one-to-one and many-to-many relationships.

     

     

    One to One

    There is a unidirectional one to one relationship defined between the Customer and Address.  Customer defines the uni directional relationship.

     

       @OneToOne(cascade = {CascadeType.ALL})
       @JoinColumn(name = "ADDRESS_ID")
       public Address getAddress()
       {
          return address;
       }
    

     

    CascadeType.ALL specifies that when a Customer is created, if there is any Address association, then that Address will be created as well(CascadeType.CREATE).  If the Customer is deleted from persistence storage, the Address table will be deleted(CascadeType.REMOVE).  If a Customer instance is reattached to persistence storage, any changes to the Address collection will be merged with persistence storage (CascadeType.MERGE).

     

    Many To Many

    There is a mant to many relationship between Customer and Flight.  In order to have a many to many relationship there needs to be a distinct join table that maps the many to many relationship.  This is called an association table.  You can have JBoss automatically generate the association table for you, or you can use the @AssociationTable annotation to define it yourself.  If you use @AssociationTable it must be defined on both sides of the bi-directional relationship.  Let's look at the Customer side of the relationship

     

       @ManyToMany(cascade = {CascadeType.CREATE, CascadeType.MERGE}, fetch = FetchType.EAGER, isInverse = true)
       @AssociationTable(table = @Table(name = "flight_customer_table"),
                         joinColumns = {@JoinColumn(name = "FLIGHT_ID")},
                         inverseJoinColumns = {@JoinColumn(name = "CUSTOMER_ID")})
    

     

    The isInverse switch specifies which side of the relationship is responsible for managing the relationship.  If it is set to false, then that side is responsible.  The spec allows for multiple join and inverse join columns.  See the Composite Primary Key tutorial for more information.

     

    Let's look at the other side of the relationship in Flight.

     

       @ManyToMany(cascade = {CascadeType.CREATE, CascadeType.MERGE}, fetch = FetchType.EAGER)
       @AssociationTable(table = @Table(name = "flight_customer_table"),
                         joinColumns = {@JoinColumn(name = "FLIGHT_ID")},
                         inverseJoinColumns = {@JoinColumn(name = "CUSTOMER_ID")})
       public Set<Customer> getCustomers()
       {
          return customers;
       }
    

     

    The database associate table will look like this:

     

       create table FLIGHT_CUSTOMER_TABLE (
          CUSTOMER_ID integer,
          FLIGHT_ID integer
       );
    

     

    Building and Running

    To build and run the example, make sure you have ejb3.deployer installed in JBoss 4.0.x and have JBoss running.  See the reference manual on how to install EJB 3.0. 

    Unix:    $ export JBOSS_HOME=<where your jboss 4.0 distribution is>
    Windows: $ set JBOSS_HOME=<where your jboss 4.0 distribution is>
    $ ant
    $ ant run
    
    run:
         [java] 2004-10-07 14:39:23,103 INFO org.jboss.remoting.InvokerRegistry[main] - Failed to load soap remoting transpo
    rt: org/apache/axis/AxisFault
         [java] Air France customers
         [java] Bill
         [java] Monica
         [java] USAir customers
         [java] Molly
    

     

    The INFO message you can ignore.  It will be fixed in later releases of JBoss 4.0.

     

    View the tables and rows

    You can view the tables created by JBoss by going to the Hypersonic SQL service, scrolling down to the startDatabaseManager button and clicking it.  A Hypersonic SQL window will be minimized, but you can open it up to look at the tables and do queries.