user152468
user152468

Reputation: 3242

Spring-Data-Jpa AuditingEntityListener createdDate updated upon saving existing entity

I have the following JPA Entity:

@EntityListeners(AuditingEntityListener.class)
@Entity
public class EntityWithAuditingDates {

    @Id
    @GeneratedValue
    private Long id;

    @Temporal(TemporalType.TIMESTAMP)
    @CreatedDate
    private Date createdDate;

    @Temporal(TemporalType.TIMESTAMP)
    @LastModifiedDate
    private Date lastModified;

    private String property;

    // getters and setters omitted.
}

And the following CrudRepository:

@Service
public interface EntityWithAuditingDatesRepository extends CrudRepository<EntityWithAuditingDates, Long> {

}

And the following test:

@SpringApplicationConfiguration(classes = FooApp.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class AuditingEntityListenerTest {

    @Autowired
    private EntityWithAuditingDatesRepository entityWithAuditingDatesRepository;

    @Test
    public void test() {
        EntityWithAuditingDates entityWithAuditingDates = new EntityWithAuditingDates();
        entityWithAuditingDates.setProperty("foo");
        assertNull(entityWithAuditingDates.getCreatedDate());
        assertNull(entityWithAuditingDates.getLastModified());
        entityWithAuditingDatesRepository.save(entityWithAuditingDates);
        assertNotNull(entityWithAuditingDates.getCreatedDate());
        assertNotNull(entityWithAuditingDates.getLastModified());
        assertEquals(entityWithAuditingDates.getLastModified(), entityWithAuditingDates.getCreatedDate());
        entityWithAuditingDates.setProperty("foooo");
        entityWithAuditingDatesRepository.save(entityWithAuditingDates);
        assertNotEquals(entityWithAuditingDates.getCreatedDate(), entityWithAuditingDates.getLastModified());
    }
}

The last condition fails. Shouldn't be the createdDate and the lastModifiedDate be different after updating the entity?

Thanks!

Upvotes: 2

Views: 7727

Answers (3)

Mark
Mark

Reputation: 461

It's not necessary to do another query to see fields updated. The repository's save method returns an object, which the documentation says that you should always use for further operations. The returned object should pass that last assertion. Try this:

entityWithAuditingDates = entityWithAuditingDatesRepository.save(entityWithAuditingDates);

Upvotes: 0

aalmero
aalmero

Reputation: 345

I faced the same issue but figured out a workaround for now. On @Column, I have set updatable=false to exclude create* fields on update.

  @CreatedBy
  @NotNull
  @Column(name = "created_by", nullable = false, length = 50, updatable =  false)
  private String createdBy;

  @CreatedDate
  @NotNull
  @Column(name = "created_date", nullable = false, updatable = false)
  private ZonedDateTime createdDate = ZonedDateTime.now();

  @LastModifiedBy
  @Column(name = "last_modified_by", length = 50)
  private String lastModifiedBy;

  @LastModifiedDate
  @Column(name = "last_modified_date")
  private ZonedDateTime lastModifiedDate = ZonedDateTime.now();

Upvotes: 9

user152468
user152468

Reputation: 3242

If you retrieve the entity from the database after the update operation, the fields are set correctly. The test case below passes. Still, I wonder why they are set correctly on the first save operation, but then incorrectly upon the second. And you only get the correct information in the end when you retrieve the record from the database. I guess this is related to the hibernate cache.

@Test
public void test() throws InterruptedException {
    EntityWithAuditingDates entityWithAuditingDates = new EntityWithAuditingDates();
    entityWithAuditingDates.setProperty("foo");
    assertNull(entityWithAuditingDates.getCreatedDate());
    assertNull(entityWithAuditingDates.getLastModified());
    entityWithAuditingDatesRepository.save(entityWithAuditingDates);
    assertNotNull(entityWithAuditingDates.getCreatedDate());
    assertNotNull(entityWithAuditingDates.getLastModified());
    assertEquals(entityWithAuditingDates.getLastModified(), entityWithAuditingDates.getCreatedDate());
    entityWithAuditingDates.setProperty("foooo");
    Thread.sleep(1000);
    entityWithAuditingDatesRepository.save(entityWithAuditingDates);
    EntityWithAuditingDates retrieved = entityWithAuditingDatesRepository.findOne(entityWithAuditingDates.getId());
    assertNotNull(retrieved.getCreatedDate());
    assertNotNull(retrieved.getLastModified());
    assertNotEquals(retrieved.getCreatedDate(), retrieved.getLastModified());
}

Upvotes: -1

Related Questions