Please explain about insertable=false and updatable=false in reference to the JPA @Column annotation

Viewed 189250

If a field is annotated insertable=false, updatable=false, doesn't it mean that you cannot insert value nor change the existing value? Why would you want to do that?

@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(mappedBy="person", cascade=CascadeType.ALL)
    private List<Address> addresses;
}

@Entity
public class Address {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne
    @JoinColumn(name="ADDRESS_FK")
    @Column(insertable=false, updatable=false)
    private Person person;
}
8 Answers

According to Javax's persistence documentation:

Whether the column is included in SQL UPDATE statements generated by the persistence provider.

It would be best to understand from the official documentation here.

Another reason could be that your attribute is mapper to a column of a view (Example, your hibernate entity is the fusion of a table and a view). So it does not make sens that your column can be inserted (nor updated).

@Entity
@Table(name = "THE_VIEW")
@SecondaryTable(name = "THE_TABLE", pkJoinColumns = @PrimaryKeyJoinColumn(name = "THE_ID"))
public class MyEntity {

    @Id
    @Column(name = "THE_ID")
    private Integer id;

    @Column(name = "VIEW_COLUMN", updatable = false, insertable = false)
    private String viewColumn

    @Column(name = "TABLE_COLUMN", table = "THE_TABLE")
    private String tableColumn;

(I don't talk about updatable views here)

Adding to the previous answers, a common use of insertable=false, updatable=false is to save redundant database queries, thereby improving performance.

Imagine having a Client class, which has a Parent entity. If you just want to check if a Client has a Parent, you simply need to check for the presence of value in its parent_id column. There is no need to ask Hibernate to fetch the Parent entity, with possibly all of its other associations, leading to additional number of queries:

public class Client {
    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST}, fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private Parent parent;

    @Column(name = "parent_id", insertable = false, updatable = false)
    private UUID parentId;
}

With the setup above, the parentId field will simply fetch whatever value is stored in the parent_id column, which is solely edited/updated by the Parent entity.

Related