Skip to main content

Need a Primary Key? Let Me Show You the Ways

Posted by bleonard on December 5, 2006 at 7:15 AM PST

When you're adding a table record and need a primary key, you can choose to generate one yourself or let the Java Persistence API do that for you. In this entry, I'm going to review a couple of the alternatives the JPA provides you for creating primary keys.

The JPA Options

If you want JPA to generate a primary key for you, you just need to add an @GeneratedValue along with the @Id annotation:

23 @Entity
24 public class NewEntity implements Serializable {
25
26     @Id
27     @GeneratedValue
28     private Long id;

Using this simple approach, the persistence provider is going to select the key generation strategy, and it is equivalent to setting the following:

27     @GeneratedValue(strategy = GenerationType.AUTO)

The persistence provider will then choose from one of the following three generation options:

  • TABLE - the persistence provider uses a database table for managing keys.
  • SEQUENCE - the persistence provider uses a databases sequence for key generation. The database must support Sequences.
  • IDENTITY - the persistence provider defers to the database for key generation. The database must support the IDENTITY column type.

For this blog I'm using Oracle's TopLink Essentials and Derby as my database. Although I may be restricted to how TopLink Essentials behaves or Derby's capabilities, the concepts discussed here apply to all persistence providers and databases.

Setting Things Up

To continue we need NetBeans 5.5 and the Java EE Application Server 9.0 (which bundles both TopLink Essentials and Derby). If you need both, just download and install the bundle.

Once installed, we're going to up the application server's logging level so we can see the SQL generated by TopLink. Follow these steps:

  1. Switch to the Runtime window (Ctrl+5).
  2. Expand the Servers node and right-click the Sun Java System Application Server node.
  3. Select View Admin Console.
  4. Unless you changed it, the default User Name should be admin. The default Password: adminadmin. Login.
  5. Click the Application Server node.
  6. Select the Logging tab.
  7. Select the Log Levels sub-tab.
  8. Set the Persistence level to FINE:




  9. Click Save.

Going on AUTO

  1. Create a new Web Application Project named KeyGen.
  2. Start the Entity Class wizard (Ctrl+N, Persistence > Entity Class)
    1. Leave the Class Name as NewEntity and Set the Package to Entity
    2. Click Create Persistence Unit
      1. Select jdbc/sample as the Data Source.
      2. Change the Table Generation Strategy to Drop and Create. (This is because we will be regenerating the table over and over again as we change primary key generation strategies)






      3. Click Create and Finish


    You now have a basic entity class that starts like the following:



    23 @Entity
    24 public class NewEntity implements Serializable {
    25
    26     @Id
    27     @GeneratedValue(strategy = GenerationType.AUTO)
    28     private Long id;

    Very similar to the code segment above, except for the default generation strategy is specified.


  3. To make the table just a bit more interesting, add another attribute, for example, firstName:



    30     private String firstName;

  4. On an empty line below the firstName attribute, press Ctrl+Space to create a getter and setter for firstName:






  5. Switch to the Projects window (Ctrl+1), right-click the KeyGen project and select Deploy Project.



    As the project is deployed, you'll see the following SQL in the output tab (only if you've changed the server's log level to FINE as described above):







    Notice 2 tables, were created, NEWENTITY and SEQUENCE. You can also see the tables in the Runtime tab (if you need to connect, the password is app):







    So, which key generation strategy does TopLink use? If you guessed SEQUENCE, you're wrong. It's TABLE. SEQUENCE just happens to be the name TopLink uses as it's generated table name. Watch, let's specifically set the strategy to TABLE and see what happens.

Deciding on TABLE

Here were going to specifically set the generation strategy to TABLE.

  1. In NewEntity.java, change the generation type from AUTO to TABLE:



    27     @GeneratedValue(strategy = GenerationType.TABLE)
  2. Deploy the application again and look at the SQL and the resulting tables. Nothing's changed. However, let's say we want to customize the key generation table. JPA allows us to do that using the @TableGenerator annotation.

Using @TableGenerator

Using @TableGenerator, you can customize the name of the table, the name name of the table's columns and even the value of the key field. For now, we'll just customize the table name. To do that, we create an @TableGenerator like follows:

  1. Add the following @TableGenerator annotation to the id field:



     29     @TableGenerator(name="NE_IDGEN", table="NEWENTITY_KEYGEN")

    Notice we have to assign the generator a name. This is so we can link it to the @GeneratedValue annotation.


  2. Add the generator argument to the @GeneratedValue annotation.



     27     @Id
    28     @GeneratedValue(strategy = GenerationType.TABLE, generator="NE_IDGEN")
    29     @TableGenerator(name="NE_IDGEN", table="NEWENTITY_KEYGEN")
    30     private Long id;


  3. Deploy the application and notice the key table is now NEWENTITY_KEYGEN:


Trying out IDENTITY

The IDENTITY generation strategy is a straight pass through to the database. The persistence provider does nothing.

  1. Change the GenerationType from TABLE to IDENTITY.
  2. Delete the generator argument
  3. Delete the @TableGenerator
  4. Your code should now look as follows:



     27     @Id
    28     @GeneratedValue(strategy = GenerationType.IDENTITY)   
    29     private Long id;
  5. Deploy the application. This time, only one SQL statement is executed. Notice the ID field is created AS IDENTITY:




Trying out SEQUENCE

Oops, Derby doesn't support Sequences, so I'll leave this one for you to experiment with on your own.

Testing the KeyGenerators

If you want to test these various generation strategies, you can create a quick user interface for your application by running the JSF Pages from Entity Class wizard. For example:

  1. Press Ctrl+N to start the New File wizard and select Persistence > JSF Pages from Entity Class.
  2. Add the NewEntity (entity) class to the Selected Entity Classes list and click Next.
  3. Set the package to view and click Finish.
  4. Press F6 to run the application.
    1. Select List of NewEntity.
    2. Select New NewEntity.
    3. Enter a name and click Create. Notice there's no need to worry about the primary key:













      This interface will work with any of the key generation strategies, so you can easily switch back to TABLE, SEQUENCE (if your database supports it) or AUTO and test run the application again.
Related Topics >>