7

I have a JPA/EclipseLink model with multiple parameters whose values are set as defaults by the PostgreSQL database. Specifically, I have:

  • An id column of type SERIAL which auto-increments when new rows are added
  • A created_at column of type TIMESTAMP which defaults to now()

My model looks like this:

import javax.persistence.*;

@Entity
@Table(name="entity")
@NamedQuery(name="Entity.findAll", query="SELECT e from Entity e")
public class Entity {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

    @Column(name="created_at")
    private java.sql.Timestamp createdAt;

    // constructor, getters, and setters
}

When I try to insert a row with persist() in javax.persistence.EntityManager, the insertion fails because a NULL value is being set for the created_at column. Rather than inserting NULL, I want to simply not insert anything into that column and allow PostgreSQL to set it to now(). Essentially, I would like to use @GeneratedValue on createdAt, but that annotation is only for primary keys and cannot be used on multiple attributes. Is there another annotation I can use that will accomplish this?

Ecliptica
  • 760
  • 2
  • 8
  • 21

3 Answers3

11

You may want insertable=false in the Column annotation:

@Column(name="created_at", insertable=false)
private java.sql.Timestamp createdAt;

From: http://docs.oracle.com/javaee/5/api/javax/persistence/Column.html

boolean insertable (Optional) Whether the column is included in SQL INSERT statements generated by the persistence provide

Glenn
  • 8,932
  • 2
  • 41
  • 54
3

You can add @DynamicInsert on your entity class. The insert statement will include null fields when without this annotation. Also, you can add @ DynamicUpdate when executing the update statement.

@Entity
@DynamicInsert
@DynamicUpdate
@Table(name="entity")
@NamedQuery(name="Entity.findAll", query="SELECT e from Entity e")
public class Entity {
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

    @Column(name="created_at")
    private java.sql.Timestamp createdAt;

    // constructor, getters, and setters
}
Stephen Ni
  • 61
  • 4
1

As mentioned in another answer, JPA providers will set the value on insert if you have it marked as insertable=true (the default). This occurs with many providers even if null as it allows statement reuse.

Just excluding it from the statement though might not be what you want, as to have the value in your entity (and in the cache) will require refreshing. EclipseLink though has @ReturningInsert which allows EclipseLink to update the entity with the value in the database. Unfortunately support is only for Oracle - other databases require use of stored procedures to return run the insert and return the value.

Chris
  • 20,138
  • 2
  • 29
  • 43