Creating Entity classes using JPA and annotations requires that your class have at least one member annotated with
@Id. Sometimes we don’t have the luxury of a table that already has a primary key field or any key fields.
In my day-to-day development, working with a DB2400 database, non-keyed tables are quite frequent. It’s not because that’s what DB2400 wants you to do, it’s just that keyed fields are simply not enforced. This creates a challenge when using an ORM framework or JPA and you need to map your Entity class to these tables. In general, even if your table is not keyed, in order for you to map an Entity class to that table, you’ll have to be able to identify a group of fields in that table that can make up a composite key that you can map too. In a recent project of mine, a phone log table had 3 columns I could group together as a composite key. The date of the phone call, the time of the phone call and the phone extension the call originated from. The theory being one person could not initiate 2 simultaneous calls from the exact same extension.
In JPA, there’s a couple ways to create composite key fields. I’ll be covering the method using the @Embeddable annotation. Let’s start with the Entity class.
This is a pretty simple Entity class with an
@Version field and a few
@Column definitions. Without going into too much detail, you’ll see that the
@Version field is also annotated
@Transient. I’ve done this simply because my table also doesn’t have a column for tracking versions, but my database is journaled, so I’m not too concerned about versioning. You’ll also notice that the
@Column fields have a value of
char set on the
columnDefinition attribute. This is because the fields in my table are defined as
char and not
varchar. If they were
varchar, I wouldn’t need to do this since a
String maps to a
varchar field by default.
@Id field is what I’m interested in right now. It’s not a standard Java type, but a class I’ve defined myself. Here is that class.
To make this class capable of being an
@Id field on an entity class, it needs to be annotated with
@Embeddable like I mentioned earlier. The 3 fields I’ve selected for my composite key are just normal
@Column definitions. Rather than create getters/setters for each field, I’ve simply implemented a constructor that takes values for all 3 fields, making any instance immutable. When annotating a class with
@Embeddable, that class will need to implement
Serializable. So I’ve added a default
serialVersionUID to accomodate.
Now that you have a class created and annotated with
@Embeddable, you can now use it as the type for an
@Id field in your entity class. Simple stuff eh.