!!!Composite Primary Keys and Primary Key Classes
The EJB 3.0 specification allows you to define a primary key class as a @Embeddable and use it as the primary key of your Entity bean.  One or
more properties can be used as members of the primary key for that particular table.  This tutorial is an adaptation of the
''relationships'' tutorial.  It adds a primary key class to Customer that holds both the ''name'' and ''id'' of the Customer.

{{{
@Embeddable
public class CustomerPK implements java.io.Serializable
{
   private long id;
   private String name;


   public CustomerPK()
   {
   }

   public CustomerPK(long id, String name)
   {
      this.id = id;
      this.name = name;
   }

   public long getId()
   {
      return id;
   }

   public void setId(long id)
   {
      this.id = id;
   }

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }

   public int hashCode()
   {
      return (int) id + name.hashCode();
   }

   public boolean equals(Object obj)
   {
      if (obj == this) return true;
      if (!(obj instanceof CustomerPK)) return false;
      if (obj == null) return false;
      CustomerPK pk = (CustomerPK) obj;
      return pk.id == id && pk.name.equals(name);
   }
}
}}}

!Mapping the primary key class
Open up [Customer|src/org/jboss/tutorial/composite/bean/Customer.java] and look for the {{getPk()}} method.  This
defines the primary key class.

{{{
   @EmbeddedId
   public CustomerPK getPk()
   {
      return pk;
   }
}}}

The [CustomerPK|src/org/jboss/tutorial/composite/bean/CustomerPK.java] class is mapped to [Customer|src/org/jboss/tutorial/composite/bean/Customer.java]
just like any other embeddable object.  The additional {{@EmbeddedId}} annotation specifies that it will be the primary key.
NOTE: If you provide a primary key class, JBoss cannot autogenerate the key
for you.  You must allocate a CustomerPK class and instantiate it with your id and name when you create the Customer.


!Many To Many
There is a mant to many relationship between [Customer|src/org/jboss/tutorial/composite/bean/Customer.java] and [Flight|src/org/jboss/tutorial/composite/bean/Flight.java].
  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 need to use the {{@JoinTable}} annotation to define this join table.
  The {{@JoinTable}} must be defined on both sides of the bi-directional relationship.  Let's look at the Customer side of the relationship

{{{
   @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.EAGER, mappedBy="customers")
   @JoinTable(name="flight_customer_table",
              joinColumns={@JoinColumn(name = "FLIGHT_ID")},
              inverseJoinColumns={@JoinColumn(name = "CUSTOMER_ID"), @JoinColumn(name = "CUSTOMER_NAME")})
   public Set<Flight> getFlights()
   {
      return flights;
   }
}}}

The {{mappedBy}} attribute specifies which side of the relationship is responsible for managing the relationship.  If it is not set, then that side is responsible.
So, for this example, the {{Flight}} Entity is responsible for managing the relation.
In this example, we are specifying multiple {{inverseJoinColumns}} because Customer has a composite primary key.

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

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

The {{Flight}} Entity must also define the {{@ManyToMany}} and {{@JoinTable}}.

The database associate table will look like this:

{{{
   create table FLIGHT_CUSTOMER_TABLE (
      CUSTOMER_ID integer,
      CUSTOMER_NAME varchar,
      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|http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB], 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.

