54

I currently have an Entity as below:

@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long productId;
    private String productImage;
    private String productTitle;
    private String productDescription;
    private Integer productPrice;
    private Date createdAt;
    private Date updatedAt;

Upon creation of this object, the value of createdAt and updatedAt shows null in the database and was wondering how I can implement code so that createdAt and updateAt automatically gets inserted?

My post method is as below:

@PostMapping("/products")
public ProductResponse createProduct(@Validated @RequestBody ProductForm productForm) {
    Product product = productForm.asProduct();
    Product createdProduct = productRepository.save(product);
    return new ProductResponse(createdProduct, "Product created");
}
dimitrisli
  • 20,895
  • 12
  • 59
  • 63
Brett Freeman
  • 571
  • 1
  • 6
  • 8

4 Answers4

74

JPA

There isn't anything as convenient as annotating the Timestamp field directly but you could use the @PrePersist, @PreUpdate annotations and with little effort achieve the same results.

Hibernate

Spring Data JPA

dimitrisli
  • 20,895
  • 12
  • 59
  • 63
  • 1
    Will this set the system's time or the database system's time? I have the problem that sometimes the system time might be wrong and have no control over it, while the db system's time is correct (and more importantly unique) – ntg Jun 07 '21 at 09:23
30

Extend the following abstract class in your entity:

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class DateAudit implements Serializable {
    @CreatedDate
    @Column(name = "created_at", nullable = false, updatable = false)
    private Date createdAt;

    @LastModifiedDate
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
}

Don't forget to enable JPA Auditing feature using @EnableJpaAuditing

Read this: https://docs.spring.io/spring-data/jpa/docs/1.7.0.DATAJPA-580-SNAPSHOT/reference/html/auditing.html

Sarvar Nishonboyev
  • 12,262
  • 10
  • 69
  • 70
  • in my case, i don't have any superclasses and base entities, and no `@EnableJpaAuditing` either, and `created_at` is set on every row insert and `updated_at` is set on every row update. is that because i'm using hibernate? – mangusta Jul 03 '22 at 19:24
  • If you are not using Spring, then you are correct. `EnableJpaAuditing` is in the Spring package `org.springframework.data.jpa.repository.config` – nonNumericalFloat Apr 03 '23 at 15:16
23

With the mix of @dimitrisli and @buddha answers, something pretty clean is

@Data
@MappedSuperclass
public abstract class BaseEntity {

    @Column(updatable = false)
    @CreationTimestamp
    private LocalDateTime createdAt;
    @UpdateTimestamp
    private LocalDateTime updatedAt;
}

And now you all your entity can extend that class like so

@Data
@Entity
@EqualsAndHashCode(callSuper = true)
public class User extends BaseEntity {

    @Id
    @GeneratedValue
    public UUID id;
    public String userName;
    public String email;
    public String firstName;
    public String lastName;
}

Note that you might not need @Data & @EqualsAndHashCode annotations from lombok as it generate getter/setter

Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
Francis Robitaille
  • 575
  • 1
  • 5
  • 18
16

You can create a BaseEntity. Each entity extends the BaseEntity. In the Base entity ,it will set the time automatically

@Data
@MappedSuperclass
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BaseEntity implements Serializable {

    @Id
    @Column(name = "Id")
    private String id;

    @Column(name = "deleted", columnDefinition = "Bit(1) default false")
    private boolean deleted = false;

    @Column(name = "DataChange_CreatedBy", nullable = false)
    private String dataChangeCreatedBy;

    @Column(name = "DataChange_CreatedTime", nullable = false)
    private Date dataChangeCreatedTime;

    @Column(name = "DataChange_LastModifiedBy")
    private String dataChangeLastModifiedBy;

    @Column(name = "DataChange_LastTime")
    private Date dataChangeLastModifiedTime;

    @PrePersist
    protected void prePersist() {
        if (this.dataChangeCreatedTime == null) dataChangeCreatedTime = new Date();
        if (this.dataChangeLastModifiedTime == null) dataChangeLastModifiedTime = new Date();
    }

    @PreUpdate
    protected void preUpdate() {
        this.dataChangeLastModifiedTime = new Date();
    }

    @PreRemove
    protected void preRemove() {
        this.dataChangeLastModifiedTime = new Date();
    }
}
buddha
  • 795
  • 5
  • 11