我使用Spring Boot 1.5.3,Spring JPA和Hibernate 5.2.10创建了一个小测试用例。当我在使用Hibernate envers的应用程序中发现奇怪的事情时,我创建了这个测试用例:我在审计表中有几行具有相同的数据。所以,如果实体没有改变,我在审计表中有了一个新行。
然后我创建了这个关注Hibernate的测试用例。我创建了一个简单的实体:
@Entity
@EntityListeners({ AuditingEntityListener.class})
public class TestEntity extends AbstractPersistable<Long> {
private static final long serialVersionUID = -7939807161238741482L;
private String name;
// Trick to start version counting from 1 instead of 0
@Version
private int version = 1;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public LocalDateTime getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(LocalDateTime lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
}
这里没什么特别的;只是允许自动设置latModifiedDate的AuditingEntityListener。 这是测试用例:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
public class HibernateTests {
private Logger log = LogManager.getLogger();
@Autowired
private TestEntityRepository testEntityRepository;
@Before
public void setup() {
testEntityRepository.deleteAll();
}
@Test
public void checkVersionAfterUpdateWithoutChanges() {
TestEntity testEntity = new TestEntity();
testEntity.setName("Name");
testEntity = testEntityRepository.save(testEntity);
assertEquals(1, testEntity.getVersion());
// saving again the user without changes
testEntity = testEntityRepository.save(testEntity);
assertEquals(1, testEntity.getVersion());
}
}
注意我没有使用@Transactional,因为我想模拟不同的事务保存对象。 我在做什么?我创建了一个TestEntity对象,我保存了它,我检查的版本是1.这个断言成功了。然后我重新保存了相同的对象,没有任何更改,我希望Hibernate没有对数据库进行任何更新,而是断言失败,因为它返回2作为版本。
从我的实体中删除AuditingEntityListener而不是测试通过! 这是一个理想的行为吗?当对象完全没有改变时,如何避免Hibernate进行更新?
=============================================
小更新:我调试了Hibernate代码,直到遇到问题为止:TypeHelper.findDirty()。正如所料,该方法发现lastModifiedDate已更改(它返回一个数组,其中字段的索引已更改)。 在脏检查控件之后不应该更新lastModifiedDate吗?仅当某些属性发生更改时才应更新对象,但更改修改日期将使对象始终在数据库中更新。我没有看到这一点......