Search code examples
jpamany-to-many

Storing ManyToMany with extra column using merge method


I have an entity class that is simply a ManyToMany with extra column, as follows:

@Entity
@Table(name = "view_templates_device_types")
public class ViewTemplateDeviceTypeEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @ManyToOne
    @JoinColumn(name = "view_template_id")
    private ViewTemplateEntity viewTemplate;

    @Id
    @ManyToOne
    @JoinColumn(name = "device_type_id")
    private DeviceTypeEntity deviceType;

    @Column(name = "priority", nullable = false)
    private int priority;

    public ViewTemplateDeviceTypeEntity() {

    }
    ...
}

I noticed that when I create a new object of this type, set viewTemplate and deviceType to values that have corresponding data in the db and I call entityManager.persist(entity) the data is stored. But when I call entityManager.merge(entity) instead of persist I get an exception:

SQL Error: 1048, SQLState: 23000
Column 'view_template_id' cannot be null

I thought that calling merge should result with data inserted into database in case it is not stored yet. It is quite important to me to use merge here (because of cascades). What can I do to make it work?


Solution

  • As per the JPA spec, section 2.4 "A composite primary key must correspond to either a single persistent field or property or to a set of such fields or properties as described below. A primary key class must be defined to represent a composite primary key. Composite primary keys typically arise when mapping from legacy databases when the database key is comprised of several columns. The EmbeddedId or IdClass annotation is used to denote a composite primary key. See Sections 11.1.17 and 11.1.22.".

    So you either need @IdClass or @EmbeddedId. Anything else is non-portable and prone to error. I am very surprised of any JPA provider that does not throw out warnings for this.