JPA2 OneToMany without primary key on the ‘Many’ side

JPA entities must have a primary key. However, there are cases where a primary key is superfluous. Instead of defining a useless primary key column just to satisfy an object model, JPA2 offers the possibility to use collections of embeddable objects.

If we imagine the following table relation (PostgreSQL), one without primary key for the second table:

:
 CREATE TABLE translatables (
    id BIGINT NOT NULL CONSTRAINT translatable_pk PRIMARY KEY,
    code VARCHAR(80) NOT NULL,
    category VARCHAR(20) NOT NULL);

 CREATE TABLE translatables_translations (
    translatable_id BIGINT NOT NULL,
    lang_code VARCHAR(2) NOT NULL,
    text VARCHAR(1024),
    UNIQUE(translatable_id, lang_code),
    CONSTRAINT translatables_fk FOREIGN KEY(translatable_id)
                                    REFERENCES translatables(id));
 :

Note: we could replace the UNIQUE constraint by a primary key, but it’s not the right solution because it is simply not the natural primary key.

We can use the following JPA2 construct to represent this in our application:

@Entity
 @Table(name="translatables")
 public class Translatable implements Serializable {

   @Id
   @GeneratedValue(/* use your favorite generator here */)
   private Long id;
   private String code;
   private String category;

   @ElementCollection(targetClass=Translation.class)
   @CollectionTable(name="translatables_translations",
          joinColumns=@JoinColumn(name="translatable_id"))
   private List translations;
 :
 }

 @Embeddable
 public class Translation implements Serializable {

   @Column(name="translatable_id")
   private Long translatableId;

   @Column(name="lang_code")
   private String langCode;

   private String text;
   :
 }
 :

Leave a Reply

Your email address will not be published. Required fields are marked *