简体   繁体   中英

@CreatedDate set to null on update (spring-data-jdbc)

I am trying to use @CreatedDate in combination with spring-data-jdbc and a PostgreSQL database to track when a table entry was first created. This works when a new row is inserted (it correctly sets it as the current date), but when updating the entry, I get exceptions because it is getting set to null which is not allowed by my configuration.

This is my entity (left out other non-relevant fields):

@Table("my_entity")
public class MyEntity {

    @Id
    private final Long id;

    @Column("created_at")
    @CreatedDate
    private Instant createdAt;

    public MyEntity (Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    public Instant getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Instant createdAt) {
        this.createdAt = createdAt;
    }
}

This is my repository:

public interface MyRepository extends CrudRepository<MyEntity, Long> {}

And this is the relevant configuration:

@Configuration
@EnableJdbcRepositories("com.example")
@EnableJdbcAuditing
public class JdbcConfig extends AbstractJdbcConfiguration {
}

Using the repository.saveAll() method, the createdAt field is correctly set the first time. When updating an existing entity with the same method, it is getting set to null when I would expect the field to get skipped.

I already tried the following:

  • Removing public getters and setters as suggested for spring-data-rest (seehere ) - didn't change anything
  • Setting @Column(name="created_at", updatable="false") as suggested for JPA (see here ) - this field is not available for the annotation I'm using ( org.springframework.data.relational.core.mapping.Column )

The two solutions I've found so far is to either use a database trigger or manually retrieve the entity from the database prior to updating it and setting the created date manually (also mentioned here ). Are there any other options or did I configure something wrong? Is this expected behaviour?

As you found, the solutions are:

  1. Set your createdAt manually when you full update . ( full update means creating a new instance with the existing id)
  2. Partial update ( partial update means you get your record to the persistence context, by using findById for example, then update it and save it back)

When you enable @EnableXXXAuditing , it will determine whether your repo.save() is insert or update , and then update your @CreatedDate and @LastModifiedDate respectively.

In your case: full update with createdAt wasn't set. Spring Data JDBC will be based on your record ID to determine whether your record should be inserted or updated Entity State Detection Strategies . If it sees the ID existed, it'll do the update . The behavior of @EnableXXXAuditing for the update is only set @LastModifiedDate so your createdAt was still null . That's why you got into trouble.

FYI: a short explanation about @EnableXXXAuditing here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM