保存现有实体

时间:2015-11-03 13:51:45

标签: java spring hibernate jpa spring-data-jpa

我有以下JPA实体:

@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.
}

以下CrudRepository:

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

}

以下测试:

@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());
    }
}

最后一个条件失败了。更新实体后,不应该是createdDate和lastModifiedDate不同?

谢谢!

3 个答案:

答案 0 :(得分:7)

我遇到了同样的问题,但现在想出了一个解决方法。在@Column上,我设置了updatable = false以在更新时排除create *字段。

  @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();

答案 1 :(得分:0)

没有必要再进行一次查询来查看更新的字段。存储库的save方法返回一个对象,the documentation表示您应始终用于进一步操作。返回的对象应该传递最后一个断言。试试这个:

entityWithAuditingDates = entityWithAuditingDatesRepository.save(entityWithAuditingDates);

答案 2 :(得分:-1)

如果在更新操作后从数据库中检索实体,则会正确设置字段。下面的测试用例通过。不过,我想知道为什么它们在第一次保存操作时设置正确,但在第二次保存操作时却不正确。当您从数据库中检索记录时,您最终只能获得正确的信息。我想这与hibernate缓存有关。

@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());
}