203

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;
}
risingTide
  • 1,754
  • 7
  • 31
  • 60
Thang Pham
  • 38,125
  • 75
  • 201
  • 285

8 Answers8

160

You would do that when the responsibility of creating/updating the referenced column's entity isn't in the current entity, but in another entity.

Karthik
  • 23
  • 1
  • 6
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 5
    You are saying that with updatable=false on Person it will disable updating of Person.name when updating address (I disagree as this is the purpose of cascade). Also u are saying that @Column definition does something different when its foreign key (Person) and when it is not foreign key (as there is no referenced entity to disable updating). By reading javadoc for updatable I would say that it will just disable to change Person for given Address if it is once persisted. Can you explain please? – Flowy Oct 03 '16 at 11:49
  • 2
    Isn't this sufficiently defined by the cascade options already? I saw this being used to not run into trouble by trying to write to a generated column. (e.g. a volume column `GENERATED ALWAYS AS (height * width * length) VIRTUAL`) – Zyl Feb 10 '21 at 09:55
148

Defining insertable=false, updatable=false is useful when you need to map a field more than once in an entity, typically:

This is IMO not a semantical thing, but definitely a technical one.

Tiny
  • 27,221
  • 105
  • 339
  • 599
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • 29
    I strongly believe that this answer is much better that the accepted one. The accepted answer conveys the feeling that insertable/updatable attribute has to do with the creation/update of the related entity, whereas the real intention behind these attributes is to prevent insertion/update of the column in the current entity. The creation/update of the related entity is tackled by the cascade attribute of the mapping annotation. – Jayant Jun 08 '15 at 17:02
33

I would like to add to the answers of BalusC and Pascal Thivent another common use of insertable=false, updatable=false:

Consider a column that is not an id but some kind of sequence number. The responsibility for calculating the sequence number may not necessarily belong to the application.

For example, sequence number starts with 1000 and should increment by one for each new entity. This is easily done, and very appropriately so, in the database, and in such cases these configurations makes sense.

Magnilex
  • 11,584
  • 9
  • 62
  • 84
  • 2
    sequences are supported by JPA as well, so you could define your sequence with JPA annotations, too. – eis Oct 09 '15 at 09:40
23

An other example would be on the "created_on" column where you want to let the database handle the date creation

Johny19
  • 5,364
  • 14
  • 61
  • 99
4

I think it simply mean :

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

Reference: https://www.objectdb.com/api/java/jpa/Column

Josh
  • 61
  • 2
2

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)

ihebiheb
  • 3,673
  • 3
  • 46
  • 55
2

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.

Petar Bivolarski
  • 1,599
  • 10
  • 19
1

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.

Nimit
  • 57
  • 1
  • 7
  • It helped me understand why a column annotated with `@CreatedDate` and/or `@UpdateTimestamp` was not getting updated if it also has `@Column(...insertable=false, updatable=false)`. Thanks! – GlauberMD May 23 '22 at 23:05