Skip to main content

Using Composite Keys with JPA

Posted by bleonard on November 29, 2006 at 9:14 AM PST

The Java Persistence API is beautiful. I create a class, annotate it with @Entity and @Id and I'm on my way. That is, however, assuming the Id is of a simple type (I'm a firm believer that primary keys should be of a simple type, unrelated to the data they index.). However, if you find yourself in a situation where you must use a composite key (hopefully this is only because you're connecting to some existing data set), JPA will still work for you, although it gets a bit more complex. First of all, you can declare a composite primary key using one of two annotations: @IdClass or @EmbeddedId. In this blog, I'm going to focus on the latter.

Using @EmbeddedId

A composite primary key must be represented by a primary key class. And when using the @EmbeddedId approach, it must be annotated as @Embeddable.

@Embeddable
public class ContactPK implements Serializable {

    @Column(name = "FIRSTNAME", nullable = false)
    private String firstname;

    @Column(name = "LASTNAME", nullable = false)
    private String lastname;

    ...

The primary key in the entity class is annoated with @EmbeddedId annotation:

@Entity
public class Contact implements Serializable {

    /**
     * EmbeddedId primary key field
     */
    @EmbeddedId
    protected ContactPK contactPK;

    ...

However, it doesn't stop there. The entity class must also implement the hashcode() and equals() methods. As I mentioned in my introduction, hopefully you're only using composite keys if you already have existing tables defined that way. In the spirit of that assumption, we're going to start with a table and just use NetBeans to create our entity class.

Setting Things Up

To continue we need NetBeans 5.5 and the Java EE Application Server 9.0. If you need both, just download and install the bundle.

Creating the Table

CompositeCustomer.sql will create a table with a composite primary key populated with some sample data.

  1. Save the CompositeCustomer.sql file somewhere on your disk.
  2. Open the file in NetBeans (Ctrl+O).
  3. On the SQL editor's toolbar, you'll see a Connection drop-down box. Select the jdbc:derby://localhost:1527/sample [app on APP] entry.






  4. Click the Run SQL icon on the right of the Connection drop-down box. This will open the Connect dialog. The password is app. Click OK to connect and run the SQL script.
  5. You can now view the table in the Runtime window:




Generating Entities With Composite Keys

The setup was the hard part. To create the entity class:

  1. Create a new Web Application project named CompositeKey.
  2. Add a new file (Ctrl+N) and select Persistence > Entity Classes from Database
    1. Select jdbc/sample as the Data Source and COMPOSITE_CUSTOMER as the table. Click Next.
    2. Set the Package to entity and click Create Persistence Unit.
      1. On the Create Persistence Unit dialog, just click Create.
    3. Click Finish

And you're done. The wizard created the primary key class, CompositeCustomerPK as well as the entity CompositeCustomer.



Testing the Entity

Here we'll delete our table and let JPA re-create it for us.

  1. Switch to the Runtime window, select the COMPOSITE_CUSTOMER table and press Delete.
  2. Switch to the Projects window and open up persistence.xml (under the Configuration Files folder). Change the Table Generation Strategy to Create
  3. Right-click the CompositeKey project and select Deploy Project. This will start the Sun Java System Application Server, if not already running, and deploy the project.
  4. Switch back to the Runtime window, right-click the Tables folder and select Refresh. JPA has re-created the table for us (sans the sample data, of course).
Related Topics >>