JPA Annotation @Column(insertable=false) is being ignored, why?

Viewed 2016

I want one of the fields to be ignored when called save() method. The field is gonna get populated automatically by the database and returned. It should be treated as a read-only field.

I am concerned about private Timestamp ts; field:

@Entity
@Table(name = "time_series", schema = "ms")
@IdClass(Reading.class)
public class Reading implements Serializable {

   private static final long serialVersionUID = 1L;

   @Id
   @Column(name = "name", nullable = false)
   private String sensorName;

   @Id
   @Column(name = "ts", insertable = false, updatable = false)
   private Timestamp ts;

   @Column(name = "reading")
   private Double value;
   ...

As you see, I use insertable = false, updatable = false are inside the @Column annotation, so I'd expect that ts is ignored when forming the actual SQL behind the curtain.

@Override
@Transactional(readOnly = false)
public Reading save(Reading r) {        
    return readingRepository.save(r);
}

ReadingRepository is basically extended Spring's CrudRepository which has save(...) method.

When I save Reading object with ts=null I get an error from Postgres:

ERROR: null value in column "ts" violates not-null constraint

because Spring Data did not actually ignore the ts field based what I see from the log:

insert into ms.time_series (ts, name, reading) values (NULL, 'sensor1', 10.0)

Clearly, I want the query to be without ts like this:

insert into ms.time_series (name, reading) values ('sensor1', 10.0)

Why is the field not being ignored?

Now if you ask me whether my database schema is okay I say yes. When I type SQL query in console without the ts everything is fine. I even tried @Generated and @GeneratedValue annotations. Name and ts are both forming a primary key for the table, however, the result is the same if I make only one of them a PK or if I add an extra surrogate ID column. Same result...

Am I overlooking something or is there maybe a bug in the Spring framework?? I am using Spring 5.1.2 and SpringData 2.1.2

Note: If I use @Transient annotation that persists the insert query correctly but then the field is being ignored completely even on read/fetch.

Many thanks for any help with this!

2 Answers

As you say

I get an error from Postgres

If you check the docs it states:

Technically, a primary key constraint is simply a combination of a unique constraint and a not-null constraint.

That's also true for multi-column primary keys (see here)

So, if ts is part of your primary key in the database (as the @Id indicates) it's simply not possible to insert null values in that column.

IMO Hibernate/Spring got nothing to do with that as

insert into ms.time_series (ts, name, reading) values (NULL, 'sensor1', 10.0)

should be equivalent to

insert into ms.time_series (name, reading) values ('sensor1', 10.0)
Related