Need a Primary Key? Let Me Show You the Ways

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.

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:

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[2] and Derby[3] 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[4] 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:

Switch to the Runtime window (Ctrl+5).

Expand the Servers node and right-click the Sun Java System Application Server node.

Select View Admin Console.

Unless you changed it, the default User Name should be admin. The default Password: adminadmin. Login.

Click the Application Server node.

Select the Logging tab.

Select the Log Levels sub-tab.

Set the Persistence level to FINE:

Click Save.

Going on AUTO

Create a new Web Application Project named KeyGen.

Start the Entity Class wizard (Ctrl+N, Persistence > Entity Class)

Leave the Class Name as NewEntity and Set the Package to Entity

Click Create Persistence Unit

Select jdbc/sample as the Data Source.

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)

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.

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

27@GeneratedValue(strategy = GenerationType.TABLE)

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:

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.